คุณสามารถปิดสตรีมด้านนอกส่วนใหญ่ได้ในความเป็นจริงคุณไม่จำเป็นต้องเก็บสตรีมทั้งหมดที่ห่อไว้และคุณสามารถใช้ Java 7 try-with-resources ได้
try (BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
new GZIPOutputStream(new FileOutputStream(createdFile)))) {
// write to the buffered writer
}
หากคุณสมัครสมาชิก YAGNI หรือคุณไม่จำเป็นต้องใช้คุณควรเพิ่มรหัสที่คุณต้องการจริงๆเท่านั้น คุณไม่ควรเพิ่มโค้ดที่คุณคิดว่าคุณอาจต้องการ แต่ในความเป็นจริงไม่ได้ทำประโยชน์อะไรเลย
ลองใช้ตัวอย่างนี้และลองนึกดูว่าจะเกิดอะไรขึ้นถ้าคุณไม่ทำสิ่งนี้และผลกระทบจะเป็นอย่างไร?
try (
OutputStream outputStream = new FileOutputStream(createdFile);
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(outputStream);
OutputStreamWriter osw = new OutputStreamWriter(gzipOutputStream);
BufferedWriter bw = new BufferedWriter(osw)
) {
// ...
}
เริ่มต้นด้วย FileOutputStream ซึ่งเรียกร้องopen
ให้ทำงานจริงทั้งหมด
/**
* 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;
หากไม่พบไฟล์แสดงว่าไม่มีทรัพยากรที่จะปิดดังนั้นการปิดจะไม่สร้างความแตกต่าง หากไฟล์มีอยู่ควรโยน FileNotFoundException ดังนั้นจึงไม่มีอะไรที่จะได้รับจากการพยายามปิดทรัพยากรจากบรรทัดนี้เพียงอย่างเดียว
เหตุผลที่คุณต้องปิดไฟล์คือเมื่อเปิดไฟล์สำเร็จ แต่คุณได้รับข้อผิดพลาดในภายหลัง
มาดูสตรีมถัดไป GZIPOutputStream
มีรหัสที่สามารถทำให้เกิดข้อยกเว้นได้
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)
});
}
สิ่งนี้เขียนส่วนหัวของไฟล์ ตอนนี้มันเป็นเรื่องแปลกมากที่คุณจะสามารถเปิดไฟล์เพื่อเขียนได้ แต่ไม่สามารถเขียนได้ถึง 8 ไบต์ แต่ลองจินตนาการว่าสิ่งนี้อาจเกิดขึ้นได้และเราจะไม่ปิดไฟล์ในภายหลัง จะเกิดอะไรขึ้นกับไฟล์หากไม่ได้ปิด
คุณไม่ได้รับการเขียนใด ๆ ที่ไม่ได้ลบข้อมูลพวกเขาจะถูกละทิ้งและในกรณีนี้จะไม่มีการเขียนไบต์ไปยังสตรีมที่ประสบความสำเร็จซึ่งไม่ได้บัฟเฟอร์ ณ จุดนี้ แต่ไฟล์ที่ไม่ได้ปิดจะไม่อยู่ตลอดไป แต่ FileOutputStream มีไฟล์
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();
}
}
}
หากคุณไม่ปิดไฟล์เลยไฟล์จะถูกปิดอยู่ดีไม่ใช่ในทันที (และอย่างที่บอกไปว่าข้อมูลที่เหลืออยู่ในบัฟเฟอร์จะหายไปด้วยวิธีนี้ แต่ในตอนนี้ไม่มีเลย)
ผลของการไม่ปิดไฟล์ทันทีคืออะไร? ภายใต้สภาวะปกติคุณอาจสูญเสียข้อมูลบางส่วนและคุณอาจใช้คำอธิบายไฟล์หมด แต่ถ้าคุณมีระบบที่สามารถสร้างไฟล์ได้ แต่เขียนอะไรลงไปไม่ได้แสดงว่าคุณมีปัญหาใหญ่กว่า กล่าวคือยากที่จะจินตนาการว่าทำไมคุณถึงพยายามสร้างไฟล์นี้ซ้ำ ๆ แม้ว่าคุณจะทำไม่สำเร็จก็ตาม
ทั้ง OutputStreamWriter และ BufferedWriter ไม่โยน IOException ในตัวสร้างดังนั้นจึงไม่ชัดเจนว่าจะทำให้เกิดปัญหาอะไร ในกรณีของ BufferedWriter คุณจะได้รับ OutOfMemoryError ในกรณีนี้มันจะทริกเกอร์ GC ทันทีซึ่งตามที่เราเห็นจะปิดไฟล์อยู่ดี