Bạn có thể đóng luồng ngoài cùng, trên thực tế, bạn không cần giữ lại tất cả các luồng được gói và bạn có thể sử dụng thử tài nguyên Java 7.
try (BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
new GZIPOutputStream(new FileOutputStream(createdFile)))) {
// write to the buffered writer
}
Nếu bạn đăng ký YAGNI hoặc bạn không cần nó, bạn chỉ nên thêm mã bạn thực sự cần. Bạn không nên thêm mã mà bạn tưởng tượng bạn có thể cần nhưng thực tế không làm gì hữu ích.
Lấy ví dụ này và tưởng tượng những gì có thể xảy ra nếu bạn không làm điều này và tác động sẽ là gì?
try (
OutputStream outputStream = new FileOutputStream(createdFile);
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(outputStream);
OutputStreamWriter osw = new OutputStreamWriter(gzipOutputStream);
BufferedWriter bw = new BufferedWriter(osw)
) {
// ...
}
Hãy bắt đầu với FileOutputStream để gọi open
tất cả công việc thực sự.
/**
* Opens a file, with the specified name, for overwriting or appending.
* @param name name of file to be opened
* @param append whether the file is to be opened in append mode
*/
private native void open(String name, boolean append)
throws FileNotFoundException;
Nếu không tìm thấy tệp, không có tài nguyên cơ bản nào để đóng, vì vậy việc đóng tệp sẽ không tạo ra bất kỳ sự khác biệt nào. Nếu tệp tồn tại, nó sẽ ném FileNotFoundException. Vì vậy, không có gì đạt được bằng cách cố gắng đóng tài nguyên từ dòng này một mình.
Lý do bạn cần đóng tệp là khi tệp được mở thành công, nhưng sau đó bạn gặp lỗi.
Hãy nhìn vào luồng tiếp theo GZIPOutputStream
Có mã có thể ném ngoại lệ
private void writeHeader() throws IOException {
out.write(new byte[] {
(byte) GZIP_MAGIC, // Magic number (short)
(byte)(GZIP_MAGIC >> 8), // Magic number (short)
Deflater.DEFLATED, // Compression method (CM)
0, // Flags (FLG)
0, // Modification time MTIME (int)
0, // Modification time MTIME (int)
0, // Modification time MTIME (int)
0, // Modification time MTIME (int)
0, // Extra flags (XFLG)
0 // Operating system (OS)
});
}
Điều này viết tiêu đề của tập tin. Bây giờ sẽ rất bất thường khi bạn có thể mở một tệp để viết nhưng không thể ghi thậm chí 8 byte vào nó, nhưng hãy tưởng tượng điều này có thể xảy ra và chúng tôi không đóng tệp sau đó. Điều gì xảy ra với một tập tin nếu nó không được đóng lại?
Bạn không nhận được bất kỳ ghi không rõ ràng nào, chúng bị loại bỏ và trong trường hợp này, không có byte nào được ghi thành công vào luồng không được đệm vào thời điểm này. Nhưng một tệp không được đóng sẽ không tồn tại mãi mãi, thay vào đó FileOutputStream có
protected void finalize() throws IOException {
if (fd != null) {
if (fd == FileDescriptor.out || fd == FileDescriptor.err) {
flush();
} else {
/* if fd is shared, the references in FileDescriptor
* will ensure that finalizer is only called when
* safe to do so. All references using the fd have
* become unreachable. We can call close()
*/
close();
}
}
}
Nếu bạn hoàn toàn không đóng một tệp, dù sao nó cũng bị đóng, nhưng không phải ngay lập tức (và như tôi đã nói, dữ liệu còn lại trong bộ đệm sẽ bị mất theo cách này, nhưng không có gì tại thời điểm này)
Hậu quả của việc không đóng tập tin ngay lập tức là gì? Trong điều kiện bình thường, bạn có khả năng mất một số dữ liệu và bạn có khả năng hết các mô tả tệp. Nhưng nếu bạn có một hệ thống nơi bạn có thể tạo tệp nhưng bạn không thể viết bất cứ điều gì cho họ, bạn sẽ gặp vấn đề lớn hơn. tức là khó có thể tưởng tượng được tại sao bạn liên tục cố gắng tạo tập tin này mặc dù thực tế bạn đang thất bại.
Cả OutputStreamWriter và BufferedWriter đều không ném IOException vào các hàm tạo của chúng, vì vậy không rõ chúng sẽ gây ra vấn đề gì. Trong trường hợp của BufferedWriter, bạn có thể nhận được OutOfMemoryError. Trong trường hợp này, nó sẽ ngay lập tức kích hoạt một GC, như chúng ta đã thấy sẽ đóng tệp bằng mọi cách.