Apakah saya harus menutup () FileReader dan BufferedReader?

188

Saya membaca file lokal menggunakan BufferedReader melilit FileReader:

BufferedReader reader = new BufferedReader(new FileReader(fileName));
// read the file
// (error handling snipped)
reader.close();

Apakah saya perlu close()yang FileReaderjuga, atau akan pembungkus pegangan itu? Saya telah melihat kode di mana orang melakukan sesuatu seperti ini:

FileReader fReader = new FileReader(fileName);
BufferedReader bReader = new BufferedReader(fReader);
// read the file
// (error handling snipped)
bReader.close();
fReader.close();

Metode ini dipanggil dari servlet, dan saya ingin memastikan saya tidak membiarkan pegangan terbuka.

Zilk
sumber
4
Anda tahu, Anda bisa membaca sumber untuk info seperti ini. Semuanya ada di src.zip di direktori instalasi JDK, atau Anda dapat membacanya secara online di misalnya docjar.com/html/api/java/io/BufferedReader.java.html
gustafc
50
Memberitahu seseorang untuk membaca sumber lebih buruk daripada mengatakan "RTFM!". Dan bagaimana jika sumbernya memiliki bug; Secara implisit kita ingin tahu apa perilaku yang benar ?
Raedwald
1
Nah ... dari sudut pandang ini: menunjuk ke spesifikasi API tidak lebih baik dari itu. Jika sumber tidak memiliki bug yang menyebabkannya tidak berperilaku seperti itu ditentukan dalam dokumen, Anda tidak dapat mengandalkan dokumen. Jadi tidak ada cara yang baik untuk menjawab pertanyaan seperti itu.
Atmocreations
@Atmocreations Rilis pemeliharaan berikutnya dengan senang hati dapat memperbaiki bug yang Anda andalkan jika Anda hanya melihat sumbernya. Anda benar-benar perlu tahu apa perilaku yang didokumentasikan. Tidak ada yang salah dalam melihat sumbernya, tentu saja, tetapi Anda tidak dapat berasumsi bahwa sumbernya tidak akan berubah. Mengubah perilaku yang terdokumentasi biasanya jauh lebih besar daripada memperbaiki bug.
James Moore

Jawaban:

202

tidak.

BufferedReader.close()

menutup aliran menurut javadoc untuk BufferedReader dan InputStreamReader

sebaik

FileReader.close()

tidak.

Atmokasi
sumber
12
Kecuali jika konstruktor BufferedReadermelempar pengecualian. Lebih bersih hanya untuk menutup aliran yang mendasarinya, meskipun Anda harus berhati-hati terhadap dekorator dengan sumber daya dan penyangga lainnya.
Tom Hawtin - tackline
9
Javadoc tidak mengatakan apakah BufferedReader.close()menutup pembaca yang mendasarinya. Uraiannya hanya disalin dari Reader.close(). Ini mungkin perilaku yang sebenarnya dalam praktik, tetapi tidak didokumentasikan.
John Kugelman
3
Jika perilaku yang sebenarnya berbeda, maka itu harus didokumentasikan seperti itu. Kalau tidak, dokumentasi tidak berguna. Programmer harus dapat mempertimbangkan dokumentasi sebagai lengkap dan spesifik.
Atmocreations
6
Tidak masalah apakah dokumentasi yang sebenarnya harus diubah atau tidak seharusnya diubah, Reader#close()javadoc's tidak mengatakan apakah ditutup atau tidak itu dibungkus Pembaca atau tidak. Semua yang dikatakan terkait dengan hal itu adalah Closes the stream and releases any system resources associated with it.yang tidak cukup eksplisit untuk mengatakan bahwa ia menutup sumber daya. 'Lepaskan sumber daya' mungkin juga menghapus referensi ke sumber daya di BufferedReader ... yang berarti sumber daya tidak ditutup.
searchengine27
99

Seperti yang telah ditunjukkan orang lain, Anda hanya perlu menutup pembungkus luar.

BufferedReader reader = new BufferedReader(new FileReader(fileName));

Ada kemungkinan sangat kecil bahwa ini bisa bocor menangani file jika BufferedReaderkonstruktor melempar pengecualian (misalnya OutOfMemoryError). Jika aplikasi Anda dalam kondisi ini, seberapa hati-hati pembersihan Anda mungkin bergantung pada seberapa kritisnya Anda tidak menghilangkan OS sumber daya yang mungkin ingin dialokasikan ke program lain.

The dapat ditutup antarmuka dapat digunakan jika konstruktor wrapper cenderung gagal di Jawa 5 atau 6:

Reader reader = new FileReader(fileName);
Closeable resource = reader;
try {
  BufferedReader buffered = new BufferedReader(reader);
  resource = buffered;
  // TODO: input
} finally {
  resource.close();
}

Kode Java 7 harus menggunakan pola coba-dengan-sumber daya :

try (Reader reader = new FileReader(fileName);
    BufferedReader buffered = new BufferedReader(reader)) {
  // TODO: input
}
McDowell
sumber
1
"Kode Java 7 harus menggunakan pola coba-dengan-sumber daya". Terima kasih, itulah tepatnya yang saya cari. Solusi ini ditulis pada '09, sehingga paradigma coba-dengan-sumber daya mungkin harus menjadi rekomendasi baru. Selain itu, ia menawarkan jawaban yang lebih baik untuk OP atas jawaban yang diterima dan lebih tinggi.
tresf
5

Menurut sumber BufferedReader, dalam hal ini bReader.close panggil fReader.close jadi secara teknis Anda tidak perlu memanggil yang terakhir.

Csaba_H
sumber
Mengingat ada dokumentasi yang menjelaskan bagaimana seharusnya digunakan, Anda harus melihat dokumentasi terlebih dahulu - penyimpangan dalam kode adalah bug.
hmijail meratapi orang-orang yang mengundurkan diri
5

Kode sumber untuk BufferedReader menunjukkan bahwa yang mendasarinya ditutup ketika Anda menutup BufferedReader.

Brian Agnew
sumber
1
Saya benar-benar ingin memberikan ini acungan jempol untuk menghubungkan ke sesuatu yang konkret, tetapi ini hanya mengacu pada implementasi OpenJDK, dan karena JavaDocs tidak jelas Reader#close(), ini tidak memberikan bukti konkret bahwa Oracle JDK, misalnya, diimplementasikan dalam busana serupa.
searchengine27
4

Setelah memeriksa kode sumber, saya menemukan itu sebagai contoh:

FileReader fReader = new FileReader(fileName);
BufferedReader bReader = new BufferedReader(fReader);

metode close () pada objek BufferedReader akan memanggil metode close () abstrak dari kelas Reader yang pada akhirnya akan memanggil metode yang diterapkan di kelas InputStreamReader , yang kemudian menutup objek InputStream .

Jadi, hanya bReader.close () yang cukup.

Anup Verma
sumber
4
Apa yang ditunjukkan kode sumber tidak citable sebagai referensi. Apa yang dikatakan spesifikasi , dalam hal ini Javadoc, yang dapat diandalkan.
Marquis of Lorne
1

Mulai dari Java 7 Anda dapat menggunakan Pernyataan coba-dengan-sumber daya

try (BufferedReader br = new BufferedReader(new FileReader(path))) {
    return br.readLine();
}

Karena BufferedReaderinstance dideklarasikan dalam pernyataan coba-dengan-sumber daya, ia akan ditutup terlepas dari apakah pernyataan coba selesai secara normal atau tiba-tiba. Jadi Anda tidak perlu menutupnya sendiri dalam finallypernyataan. (Ini juga kasus dengan pernyataan sumber daya bersarang)

Ini adalah cara yang disarankan untuk bekerja dengan sumber daya, lihat dokumentasi untuk informasi lebih rinci

Claudiu
sumber
Ini hampir identik dengan jawaban @ mcdowell dari 2009, yang juga mencakup beberapa masalah tepi-kasus yang bisa terjadi.
tresf
0

Anda Hanya Perlu menutup bufferedReader yaitu reader.close () dan itu akan berfungsi dengan baik.

Jitendra
sumber
0

Saya terlambat, tetapi:

BufferReader.java:

public BufferedReader(Reader in) {
  this(in, defaultCharBufferSize);
}

(...)

public void close() throws IOException {
    synchronized (lock) {
        if (in == null)
            return;
        try {
            in.close();
        } finally {
            in = null;
            cb = null;
        }
    }
}
Dmitry Gashko
sumber
Eeeeh itu tidak menjawab pertanyaannya? Dia bertanya apakah perlu untuk menutup FileReader dan BufferedReader bukan kode contoh.
TornaxO7
@ TornaxO7 tidak, ini bukan kode contoh. Saya baru saja menulis bagian dari kode sumber java. Jadi, jika Anda mengklik beberapa fungsi BufferedReader dengan kunci ctrl / cmd (tergantung pada IDE) Anda dapat melihat kode sumber BufferedReader, dan Anda dapat menemukan fragmen kode itu. Jadi, seperti yang Anda lihat BufferedReader tutup FileReader dengan sendirinya ('in' adalah FileReader dalam kasus ini, jadi, ketika Anda memanggil bufferReader.close () ia memanggil in.close () di dalamnya, tepatnya di bufferReader.close method)
Dmitry Gashko
0

Anda Tidak perlu menutup pembaca / penulis yang dibungkus.

Jika Anda telah melihat pada dokumen ( Reader.close(), Writer.close()), Anda akan melihat bahwa di Reader.close()dalamnya tertulis:

Menutup aliran dan melepaskan sumber daya sistem apa pun yang terkait dengannya.

Yang hanya mengatakan bahwa ia "melepaskan sumber daya sistem apa pun yang terkait dengannya". Meskipun itu tidak mengkonfirmasi .. itu memberi Anda dorongan untuk mulai mencari lebih dalam. dan jika Anda pergi ke Writer.close()sana hanya menyatakan bahwa itu menutup sendiri.

Dalam kasus seperti itu, kami merujuk ke OpenJDK untuk melihat kode sumbernya.

Di BufferedWriter Line 265 Anda akan melihat out.close(). Jadi itu tidak menutup sendiri .. Itu sesuatu yang lain. Jika Anda mencari kelas untuk " out" kejadian, Anda akan melihat bahwa dalam konstruktor di Baris 87 yang outmerupakan penulis kelas membungkus di mana ia memanggil konstruktor lain dan kemudian menetapkan outparameter untuk itu sendiriout variabel .

Jadi .. Bagaimana dengan yang lain? Anda dapat melihat kode serupa di BufferedReader Line 514 , BufferedInputStream Line 468 dan InputStreamReader Line 199 . Lainnya saya tidak tahu tetapi ini harus cukup untuk mengasumsikan bahwa mereka tahu.

Omar Abdul'Azeez
sumber