2015-10-06 26 views
6

Czy ktoś może mi wyjaśnić dlaczego praca ta konstrukcja przyzwyczajenie:java odczytu/zapisu konstrukcji

while (fileInputStream.available()>0) {  
    fileOutputStream.write(fileInputStream.read()); 
} 

a ten działa dobrze:

while (fileInputStream.available()>0) { 
    int data = fileInputStream.read(); 
    fileOutputStream.write(data); 
} 

jak dla mnie są one identyczne, ale 1. Jeden przyzwyczajenie poprawnie zapisuj dane (zapisze połowę długości pliku/danych).

+1

Czy jest pętla, której nam nie pokazujesz? Ponieważ read() odczytuje tylko segment danych. Ogólnie rzecz biorąc, ten segment jest określany przez kontener, a int to 32-bitowe, gdzie jako plik output-stream bierze różne bajty o wielkości –

+0

Są one takie same. Zauważ, że to ** nie ** kopiuje całej zawartości strumienia wejściowego do strumienia wyjściowego. Będzie czytać i pisać tylko jeden bajt. – Jesper

+0

jeśli chcesz, aby działało, powinieneś wprowadzić bufor bajtowy http://docs.oracle.com/javase/7/docs/api/java/io/FileInputStream.html#read (byte []) –

Odpowiedz

9

Jesteś nieprawidłowo stosując metodę available(). Metoda służy do określenia, ile bajtów można odczytać bez blokowania wątku.

Good Stack Overflow Question about available()

JavaDoc on available()


Prawidłowy sposób sprawdzić, czy dotarły EOF jest sprawdzenie, czy metoda read() powrócił -1:

int data = fileInputStream.read(); 
while (data != -1) { 
    fileOutputStream.write(data); 
    data = fileInputStream.read(); 
} 

Ta metoda prawdopodobnie idzie g będzie dość powolny, jeśli spróbujesz odczytać większą ilość danych.Możesz przyspieszyć to, czytając w większej ilości bajtów, używając metody read(byte[] b, int off, int len). Pętla będzie wyglądać bardzo podobnie do drugiej.

byte [] buffer = new byte[1024]; // 1kb buffer 
int numBytesRead = fileInputStream.read(buffer); 
while (numBytesRead != -1) { 
    fileOutputStream.write(buffer, 0, numBytesRead); 
    numBytesRead = fileInputStream.read(buffer); 
} 
+0

'while (-1! = (Data = read())) write (dane);' – ZhongYu

1

Moje zainteresowanie wzbudził Napisałem ten mały test:

public static void main(String[] args) throws IOException { 

    FileInputStream fileInputStream = new FileInputStream("/home/nick/foo"); 
    FileOutputStream fileOutputStream = new FileOutputStream("/home/nick/bar"); 
    fileOutputStream.write(fileInputStream.read()); 

    fileOutputStream.flush(); 
    fileOutputStream.close(); 
    fileInputStream.close(); 
} 

to działało jak oczekiwano - Odczyt pojedynczy bajt z /home/nick/foo i napisał go /home/nick/bar

EDIT:

Zaktualizowany Program:

public static void main(String[] args) throws IOException { 

    FileInputStream fileInputStream = new FileInputStream("/home/nick/foo"); 
    FileOutputStream fileOutputStream = new FileOutputStream("/home/nick/bar"); 
    while (fileInputStream.available()>0) {  
     fileOutputStream.write(fileInputStream.read()); 
    } 

    fileOutputStream.flush(); 
    fileOutputStream.close(); 
    fileInputStream.close(); 
} 

Skopiowano cały plik. (uwaga - nie polecałbym kopiowania pliku po bajcie w tym samym czasie, użyj klas buforowanych we/wy do skopiowania całych porcji)

Czy przypadkiem zapomniałeś flush() i close() na OutputStream?

+0

I zaktualizowany pierwszy post - thougt pętla nie ma znaczenia w tym pytaniu. Jest pętla i istnieje różnica – Hikaru

+0

to działa - patrz aktualizacja – NickJ

+0

Sprawdziłem: tak, to kopiuje plik i niektóre dane mogą być odczytywane z niego, ale zawartość jest zdecydowanie uszkodzona. – Hikaru

1

Wygląda na to, że podczas wykonywania pętli wykonywana jest szacowana wartość i pomijanie tu i tam.

public int available() throws IOException { 
     return 0; 
    } 

Zwraca szacunkową liczbę pozostałych bajtów, które można odczytać (lub pomijane) z tego strumienia wejściowego bez blokowania przez następny wywołaniu metody dla tego strumienia wejściowego. Następna inwokacja może być tym samym wątkiem lub innym wątkiem. Pojedynczy odczyt lub pominięcie tej liczby bajtów nie będzie blokował, ale może odczytać lub pominąć mniej bajtów. W niektórych przypadkach niezablokowany odczyt (lub pominięcie) może wydawać się blokowany , gdy jest tylko powolny, na przykład podczas czytania dużych plików przez wolne sieci .

See here

+0

Dziękuję, wydaje mi się, że to, co się tutaj dzieje. – Hikaru