2013-01-23 34 views
20

Thoạt nhìn mã này dường như hoàn toàn OKjava.io.BufferedOutputStream có an toàn để sử dụng không?

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

nhưng nếu chúng ta hãy xem xét kỹ hơn chúng ta sẽ thấy rằng close() được thực hiện như sau

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

Có thể rằng do flush() lỗi được bỏ qua dữ liệu có thể bị mất và chương trình sẽ không nhận thấy nó? Không có đề cập đến bất kỳ mối nguy hiểm nào trong số FilterOutputStream.close (trong đó BufferedOutputStream kế thừa close() từ) API.

Cập nhật: Để mô phỏng lỗi IO trong khi đóng() tôi đã thay đổi thử nghiệm để ghi vào bộ nhớ Flash, thêm 5 giây trước khi bout.close() và trong khi thử nghiệm đang ngủ, tôi đã xóa Flash khỏi USB . Các thử nghiệm đã hoàn thành mà không có ngoại lệ, nhưng khi tôi chèn Flash và kiểm tra nó - 1.txt đã không có.

Sau đó, tôi gạt gần()

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

và chạy thử nghiệm một lần nữa và đã

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

'FilterOutputStream' typo? –

+3

Nó hiển thị như một lỗi trong phương thức 'close()' của openjdk. - Cửa hàng chết để bỏ qua ... –

+0

@Nikolay Không phải của nó. BufferedOuptutStream kế thừa từ đó, quên đề cập đến –

Trả lời

5

Vì nó là, tôi sẽ lý do đó gọi close thực sự có thể làm cho bạn bị mất dữ liệu, vì đó tiềm năng IOException đang được bỏ qua âm thầm (người trên trái đất biết những gì đã đi qua tâm trí của các nhà phát triển để làm điều đó ...).

Một thay thế đàng hoàng, mặc dù nó đặt các nỗ lực về phía các lập trình viên, là để gọi flush một cách rõ ràng trước close (xử lý các tiềm năng IOException chính xác), như đã đề cập trong một chú thích bởi @ Tom, đặc biệt là trong một khối try/finally .

Sự cố này có thể tiếp tục trầm trọng hơn trong Java7, do các đối tượng AutoCloseable, vì bạn sẽ không gọi phương thức close() một cách rõ ràng và loại công việc này thậm chí còn dễ bị trượt hơn.

+0

có lẽ vì chúng không có ngoại lệ bị loại bỏ, vì vậy chúng không biết cách xử lý ngoại lệ từ flush(). – irreputable

+1

Tôi nghĩ rằng sẽ vẫn an toàn hơn khi ném Ngoại lệ lên và cho phép người dùng biết rõ rằng đã xảy ra sự cố. – pcalcao

Các vấn đề liên quan