FileReaderとBufferedReaderの両方をclose()する必要がありますか?


188

FileReaderをラップしたBufferedReaderを使用してローカルファイルを読み取っています。

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

DO Iのに必要としても、またはラッパーのハンドルがあることだろうか?私は人々がこのようなことをするコードを見てきました:close()FileReader

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

このメソッドはサーブレットから呼び出されます。ハンドルを開いたままにしないようにしたいと思います。


4
そうですね、このような情報のソースを読むことができます。それはすべてJDKインストールディレクトリのsrc.zipにあります。または、たとえばdocjar.com/html/api/java/io/BufferedReader.java.html
gustafc

50
誰かにソースを読むように言うことは、「RTFM!」と言うより悪いです。そして、ソースにバグがある場合はどうでしょうか。暗黙的に、正しい動作が何かを知りたいですか?
Raedwald 2013

1
ええと...この観点から:API仕様を指すことは、それよりも優れているわけではありません。ソースにバグがなく、ドキュメントで指定されているように動作しない場合、ドキュメントに依存することはできません。したがって、そのような質問に答える良い方法はありません。
Atmocreations

@Atmocreations次のメンテナンスリリースでは、ソースを確認するだけで依存するバグを元気に修正できます。文書化された動作を知る必要があります。もちろん、ソースを見て問題はありませんが、ソースが変更されないとは限りません。文書化された動作を変更することは、通常、バグを修正するよりもはるかに重要です。
James Moore

回答:


202

番号。

BufferedReader.close()

BufferedReaderおよびInputStreamReaderの javadocに従ってストリームを閉じます

と同様

FileReader.close()

します。


12
コンストラクタがBufferedReader例外をスローしない限り。基礎となるストリームを閉じるだけの方がきれいですが、他のリソースとバッファリングによるデコレータに注意する必要があります。
トム・ホーティン-

9
JavadocはBufferedReader.close()、基になるリーダーを閉じるかどうかについては述べていません。その説明は単にからコピーされReader.close()ます。これは実際には実際の動作である可能性がありますが、文書化されていません。
John Kugelman、2015年

3
実際の動作が異なる場合は、そのように文書化されているはずです。そうでなければ、ドキュメントは役に立たない。プログラマーは、ドキュメントを完全かつ具体的であると見なすことができるはずです。
Atmocreations 2015

6
実際のドキュメントが変更されているべきか、変更されるべきではないReader#close()かは関係ありません。's javadoc ' は、ラップされたReaderを閉じるかどうかを通知しません。それCloses the stream and releases any system resources associated with it.に関してそれが言っているのは、それがリソースを閉じている、または閉じていない、と言うほど明確ではないということです。「リソースを解放する」は、BufferedReader内のリソースへの参照を削除するだけでなく、リソースが閉じられていないことを意味します。
searchengine27 2015年

99

他の人が指摘したように、外側のラッパーを閉じるだけで済みます。

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

BufferedReaderコンストラクターが例外をスローした場合(たとえばOutOfMemoryError)、ファイルハンドルがリークする可能性は非常にわずかです。アプリがこの状態の場合、クリーンアップをどの程度注意深く行う必要があるかは、他のプログラムに割り当てたいリソースのOSを奪わないことがどれほど重要であるかによって異なります。

閉鎖可能ラッパーのコンストラクタは、Java 5または6で失敗する可能性がある場合はインターフェースが使用できます。

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

Java 7コードでは、try-with-resourcesパターン使用する必要があります。

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

1
「Java 7コードは、try-with-resourcesパターンを使用する必要があります」。ありがとう、それがまさに私が探していたものです。このソリューションは'09に作成されたため、try-with-resourcesパラダイムがおそらく新しい推奨事項になるはずです。さらに、それは受け入れられたより高い投票された回答よりもOPへのより良い回答を提供します。
tresf

5

BufferedReaderソースによると、この場合bReader.closeはfReader.closeを呼び出すため、技術的には後者を呼び出す必要はありません。


それがどのように使用されるべきかを説明するドキュメントがあることを考えると、最初にドキュメントを見る必要があります-コードの逸脱はバグです。
hmijail氏は

5

BufferedReaderのソースコードは、BufferedReaderを閉じると、基になるものが閉じられることを示しています。


1
私はこれを具体的なものにリンクすることについて親指を立てたいと思いますが、これはOpenJDK実装のみを参照しており、JavaDocsはについて不明確であるためReader#close()、たとえば、Oracle JDKが同様のファッション。
searchengine27 2015年

4

ソースコードをチェックした後、私は例のためにそれを見つけました:

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

上のclose()メソッドをBufferedReaderのオブジェクトは、抽象のclose()メソッドを呼び出しますリーダー、最終的に実装メソッド呼び出しますクラスにInputStreamReaderのその後閉じクラス、のInputStreamオブジェクトを。

したがって、bReader.close()のみで十分です。


4
ソースコードが示す内容は、参照として引用することはできません。それは何の仕様は、この場合には、言うに信頼できるのJavadoc、。
ローン侯爵

1

Java 7以降では、try-with-resourcesステートメントを使用できます

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

BufferedReaderインスタンスはtry-with-resourceステートメントで宣言されているため、tryステートメントが正常に完了したか突然完了したかに関係なく閉じられます。したがって、finallyステートメントで自分で閉じる必要はありません。(これは、ネストされたリソースステートメントの場合も同様です)

これは、リソースを操作するための推奨される方法です。詳細については、ドキュメントを参照してください


これは、2009年の@mcdowellの回答とほぼ同じであり、発生する可能性があるいくつかのエッジケースの問題もカバーしています。
tresf

0

bufferedReader、つまりreader.close()を閉じるだけで、問題なく動作します。


0

私は遅れましたが:

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

彼/彼女の質問に答えないイーイー?彼女/彼は、サンプルコードではなく、FileReaderとBufferedReaderを閉じる必要があるかどうか尋ねます。
TornaxO7

@ TornaxO7いいえ、サンプルコードではありません。Javaソースコードの一部を書いたところです。したがって、ctrl / cmdキー(IDEによって異なります)を使用してBufferedReaderの関数をクリックすると、BufferedReaderのソースコードが表示され、そのコードのフラグメントを見つけることができます。したがって、BufferedReaderを見るとわかるように、FileReaderを単独で閉じるだけです(この場合、「in」はFileReaderなので、bufferReader.close()を呼び出すと、内部でin.close()を呼び出し、正確にbufferReader.closeメソッドを呼び出します)
ドミトリーガシュコ

0

あなたはしないでください包まれたリーダ/ライタを閉じる必要があります。

ドキュメントをご覧になった場合(Reader.close()Writer.close())を確認すると、次のReader.close()ように表示されます。

ストリームを閉じて、それに関連するすべてのシステムリソースを解放します。

それはちょうどそれが「システムリソースを解放する それに関連するます。それは確認できませんが..それはあなたにあなたがより深く見て始めるためのナッジを与えます。あなたがWriter.close()それに行く場合、それはそれ自体が閉じると述べているだけです。

そのような場合は、OpenJDKを参照してソースコードを確認します。

BufferedWriter Line 265に表示されますout.close()。だからそれはそれ自体を閉じていません。それは何か別のものです。「out」の出現をクラスで検索すると、87行目のコンストラクターに気付くでしょう。outは、別のコンストラクタを呼び出し、次に割り当てるライタークラスラップでoutそれ自身にパラメータをout変数...

それで、他の人はどうですか?同様のコードは、BufferedReader Line 514BufferedInputStream Line 468、およびInputStreamReader Line 199にあります。他の人は知りませんが、これで十分だと思います。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.