Hem FileReader hem de BufferedReader'ı kapatmam () gerekiyor mu?


188

Bir FileReader sarılı bir BufferedReader kullanarak yerel bir dosya okuyorum:

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

Do Ben gerek de ya olacak sarıcı kolu olduğunu? Ben insanlar böyle bir şey yapmak kodu gördüm:close()FileReader

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

Bu yöntem bir sunucu uygulamasından çağrılır ve hiçbir tanıtıcıyı açık bırakmadığımdan emin olmak istiyorum.


4
Biliyorsun, böyle bilgi için kaynağı okuyabilirsin. Bu JDK kurulum dizinindeki src.zip içinde hepsi orada, yoksa örnek için de çevrimiçi olarak okuyabilirsiniz docjar.com/html/api/java/io/BufferedReader.java.html
gustafc

50
Birine kaynağı okumasını söylemek "RTFM!" Demekten daha kötüdür. Peki ya kaynağın bir hatası varsa; dolaylı olarak doğru davranışın ne olduğunu bilmek istiyoruz ?
Raedwald

1
Şey ... bu bakış açısından: API spesifikasyonlarına işaret etmek o zaman daha iyi değil. Kaynakta, dokümanlarda belirtildiği gibi davranmamasına neden olan bir hata yoksa, dokümanlara güvenemezsiniz. Yani böyle bir soruyu cevaplamanın iyi bir yolu yok.
Atmocreations

@Atmocreations Bir sonraki bakım sürümü, yalnızca kaynağa bakarsanız güvendiğiniz bir hatayı neşeyle düzeltebilir. Belgelenmiş davranışların ne olduğunu gerçekten bilmeniz gerekir. Kaynağa bakarken yanlış bir şey yok elbette, ancak kaynağın değişmeyeceğini varsayamazsınız. Belgelenmiş davranışları değiştirmek genellikle bir hatayı düzeltmekten çok daha büyük bir anlaşmadır.
James Moore

Yanıtlar:


202

Hayır.

BufferedReader.close()

BufferedReader ve InputStreamReader için javadoc'a göre akışı kapatır

Hem de

FileReader.close()

yapar.


12
Yapıcı BufferedReaderistisna atmadığı sürece . Diğer kaynakları ve arabelleğe alma ile dekoratörler için dikkat etmenize rağmen, sadece altta yatan akışı kapatmak daha temizdir.
Tom Hawtin - çakmak hattı

9
Javadoc BufferedReader.close(), altta yatan okuyucuyu kapatıp kapatmayacağını söylemez . Açıklaması basitçe kopyalandı Reader.close(). Bu pratikte gerçek davranış olabilir, ancak belgelenmemiştir.
John Kugelman

3
Gerçek davranış farklıysa, bu şekilde belgelenmesi gerekir. Aksi takdirde belgeler işe yaramaz. Programcı, belgeleri eksiksiz ve spesifik olarak değerlendirebilmelidir.
Atmocreations

6
Gerçek belgelerin değiştirilmiş olması ya da değiştirilmemesi gerektiği önemli değil, Reader#close()javadoc'lar okuyucunun sarılmış Reader'ı kapatıp kapatmayacağını söylemiyor. Bununla ilgili Closes the stream and releases any system resources associated with it.söylediği tek şey, kaynağı kapattığını veya kapatmayacağını söyleyecek kadar açık değildir. 'Kaynağın serbest bırakılması', BufferedReader'daki kaynağa yapılan herhangi bir başvuruyu da kaldırıyor olabilir ... Bu da kaynağın kapalı olmadığı anlamına gelir.
searchengine27

99

Diğerlerinin işaret ettiği gibi, sadece dış sargıyı kapatmanız gerekir.

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

BufferedReaderOluşturucu bir istisna attığında bunun bir dosya tanıtıcısını sızdırma olasılığı çok düşüktür (örn. OutOfMemoryError). Uygulamanız bu durumda ise, temizliğinizin ne kadar dikkatli olması gerektiğine bağlı olarak işletim sistemini diğer programlara ayırmak isteyebileceği kaynaklardan mahrum kalmamanızın ne kadar kritik olduğuna bağlı olabilir.

Kapatılabilir bir sargı yapıcı Java 5 ya da 6 başarısız olma ihtimali ise, arayüz kullanılabilir:

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

Java 7 kodu, kaynaklarla deneme desenini kullanmalıdır:

try (Reader reader = new FileReader(fileName);
    BufferedReader buffered = new BufferedReader(reader)) {
  // TODO: input
}

1
"Java 7 kodu, kaynaklarla deneme desenini kullanmalıdır". Teşekkürler, tam da aradığım şey buydu. Bu çözüm '09'da yazılmıştır, bu nedenle kaynaklarla deneme paradigması muhtemelen yeni öneri olmalıdır. Dahası, kabul edilen ve daha yüksek oylanan cevap üzerinden OP'ye daha iyi bir cevap sunuyor.
tresf

5

BufferedReader kaynağına göre, bu durumda bReader.close, fReader.close'u arayın, böylece teknik olarak ikincisini çağırmanız gerekmez.


Nasıl kullanılması gerektiğini açıklayan belgeler olduğu göz önüne alındığında, önce belgelere bakmalısınız - koddaki herhangi bir sapma bir hatadır.
hmijail resignees

5

BufferedReader için kaynak kodu, BufferedReader'ı kapattığınızda temelin kapalı olduğunu gösterir.


1
Bunu somut bir şeye bağlamak için gerçekten bir başparmak vermek istiyorum, ancak bu sadece OpenJDK uygulamasına atıfta bulunuyor ve JavaDocs için belirsiz olduğu için Reader#close(), bu, Oracle JDK'nın benzer tarz.
searchengine27

4

Kaynak kodu kontrol ettikten sonra, örnek için buldum:

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

yakından () yöntemi BufferedReader nesnenin arka yakın () yöntemini çağırır Okuyucu sonunda uygulanan yöntem çağırır sınıf InputStreamReader sonra kapanır sınıf, inputStream nesnesi.

Bu nedenle, sadece bReader.close () yeterlidir.


4
Kaynak kodun gösterdiği referans olarak kabul edilemez. Şartnamenin söylediği şey bu durumda Javadoc'a güvenilebilir.
Lorne Marquis

1

Java 7'den başlayarak, kaynaklarla deneme ifadesini kullanabilirsiniz

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

Çünkü BufferedReaderörnek bir try-ile-kaynak açıklamada bildirilmiş, ne olursa olsun try deyimi normal veya aniden tamamlar bakılmaksızın kapalı olacaktır. Yani finallyifadede kendiniz kapatmanıza gerek yok . (Bu, iç içe geçmiş kaynak ifadelerinde de geçerlidir)

Kaynaklarla çalışmanın önerilen yolu budur, daha ayrıntılı bilgi için belgelere bakın


Bu, @ mcdowell'in 2009'daki yanıtıyla neredeyse aynıdır ve bu da ortaya çıkabilecek bazı son durum sorunlarını da kapsamaktadır.
tresf

0

Yalnızca bufferedReader'ı yani reader.close () öğesini kapatmanız yeterlidir ve iyi çalışır.


0

Geç kaldım ama:

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;
        }
    }
}

Eeeeh bu sorusunu cevaplamıyor mu? Örnek bir kod değil FileReader ve BufferedReader'ı kapatmanın gerekli olup olmadığını sorar .
TornaxO7

@ TornaxO7 hayır, örnek bir kod değil. Java kaynak kodunun bir kısmını yazdım. Bu nedenle, ctrl / cmd tuşuyla (IDE'ye bağlıdır) bazı BufferedReader işlevine tıklarsanız, BufferedReader'ın kaynak kodunu görebilirsiniz ve bu kod parçasını bulabilirsiniz. Gördüğünüz gibi, BufferedReader sadece FileReader'ı kendi başına kapatır (bu durumda 'in' FileReader'dır, bu nedenle, bufferReader.close () öğesini çağırdığınızda, tam olarak bufferReader.close yönteminde in.close () öğesini çağırır)
Dmitry Gashko

0

Sen etmeyin sarılmış okuyucu / yazıcıyı kapatmak gerekir.

Dokümanlara ( Reader.close(), Writer.close()) bir göz attıysanız , içinde Reader.close()şunu göreceksiniz :

Akışı kapatır ve onunla ilişkili tüm sistem kaynaklarını serbest bırakır.

Bu sadece "onunla ilişkili herhangi bir sistem kaynağını serbest bırakır" diyor . Doğrulamasa da .. daha derinlere bakmaya başlaman için bir dürtü veriyor. ve eğer Writer.close()ona gidersen sadece kendini kapattığını belirtir.

Bu gibi durumlarda, kaynak koduna bakmak için OpenJDK'ya başvururuz .

BufferedWriter Line 265'de göreceksiniz out.close(). Yani kendini kapatmıyor .. Başka bir şey. Eğer "tekrarlarını için sınıfını arama yaparsanız out" En oluşturucu içinde fark edeceksiniz Hat 87out atayarak yazara sonra sınıf başka yapıcısını çağırır tamamladı ve bir outo kendi parametreyi outdeğişkeni ..

Peki .. Peki ya diğerleri? Benzer kodu BufferedReader Line 514 , BufferedInputStream Line 468 ve InputStreamReader Line 199'da görebilirsiniz . Diğerleri bilmiyorum ama bu yaptıklarını varsaymak için yeterli olmalıdır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.