2013-01-23 27 views
20

Na pierwszy rzut oka ten kod wydaje się całkowicie OKCzy użycie java.io.BufferedOutputStream jest bezpieczne?

BufferedOutputStream bout = new BufferedOutputStream(new FileOutputStream("1.txt")); 
byte[] bytes = new byte[4096]; 
bout.write(bytes); 
bout.close(); 

ale jeśli przyjrzeć się bliżej zobaczymy, że close() jest realizowany w następujący sposób

public void close() throws IOException { 
    try { 
     flush(); 
    } catch (IOException ignored) { 
    } 
    out.close(); 
} 

Czy to możliwe, że ze względu na flush() błędy są ignorowane dane mogą zostać utracone, a program ich nie zauważy? Nie ma żadnej wzmianki o żadnym niebezpieczeństwie w FilterOutputStream.close (gdzie BufferedOutputStream dziedziczy po) z API.

UPDATE: Aby zasymulować błąd IO podczas close() Zmieniłem próbę zapisu do pamięci Flash, dodał Sleep 5 sekund przed bout.close() i podczas testu spała usunąłem z USB Flash . Test zakończył się bez wyjątków, ale kiedy włożyłem Flash i sprawdziłem - 1.txt nie było.

Potem overrode close()

BufferedOutputStream bout = new BufferedOutputStream(new FileOutputStream("g:/1.txt")) { 
     @Override 
     public void close() throws IOException { 
      flush(); 
      super.close(); 
     } 
    }; 

i prowadził test ponownie i dostał

Exception in thread "main" java.io.FileNotFoundException: g:\1.txt (The system cannot the specified path) 
    at java.io.FileOutputStream.open(Native Method) 
    at java.io.FileOutputStream.<init>(FileOutputStream.java:212) 
    at java.io.FileOutputStream.<init>(FileOutputStream.java:104) 
    at test.Test1.main(Test1.java:10) 
+0

Błąd "FilterOutputStream"? –

+3

Pokazuje jako błąd w metodzie openjdk 'close()'. - Martwy sklep, aby zignorować ... –

+0

@Nikolay Nie, nie jest. BufferedOuptutStream odziedziczy stamtąd blisko, zapomniałem wspomnieć o –

Odpowiedz

5

Jak to jest, że ja rozumieć, że nazywając close mogą rzeczywiście powodować utratę danych, ponieważ potencjał IOException jest cicho ignorowany (kto na świecie wie, co przeszło przez umysły programistów, aby to zrobić ...).

Przyzwoite alternatywa, choć nie wkładać wysiłek na stronie programisty, jest wywołanie flush jawnie przed close (manipulacja potencjalnego IOException poprawnie), jak wspomniano w komentarzu przez @Tom, szczególnie w bloku try/finally .

Problem ten może być dodatkowo pogarsza w Java7 powodu AutoCloseable obiektów, ponieważ nie będzie jawnie wywołać metodę close() i ten rodzaj pracy wokół jest jeszcze łatwiejsze mijają.

+0

prawdopodobnie dlatego, że nie zostały wyłączone wyjątki, więc nie wiedzieli, jak sobie poradzić z wyjątkiem z opróżniania(). – irreputable

+1

Myślę, że bezpieczniej byłoby jeszcze wyrzucić wyjątek i pozwolić, aby użytkownik wyraźnie wiedział, że coś poszło nie tak. – pcalcao

Powiązane problemy