- PR -

close()前のflush()の必要性

1
投稿者投稿内容
Cerberus
会議室デビュー日: 2003/07/23
投稿数: 2
お住まい・勤務地: 東京都
投稿日時: 2003-07-23 10:31
はじめまして、Cerberusといいます。

質問なのですが、雑誌やホームページ等のサンプルを見ていると、java.ioパッケージの出力ストリームクラスを閉じる際に、以下のようにclose()の前にflush()を呼び出しているソースをよく見かけます。

コード:
PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(filename)));

...

pw.flush();
pw.close();



しかしJDKのソースをのぞいたところ、close()内で自動的にflush()も呼ばれるようになっていました。
あえて上記のようにコーディングする理由はあるのでしょうか?

例えば

  • 古いJDKとの互換性のため。
  • JDKの仕様ではclose()内でflush()が行われるとは規定されていない。
H2
ぬし
会議室デビュー日: 2001/09/06
投稿数: 586
お住まい・勤務地: 港
投稿日時: 2003-07-23 11:58
> あえて上記のようにコーディングする理由はあるのでしょうか?
本当はないはずです。大元のClassであるWriterのclose()のJavaDocでは、
"Close the stream, flushing it first."
と書いてあります。ですので、Writerに extend しているクラスの close() はすべて、閉じる前にフラッシュをするはずです。ただし、この規約が本当に守られているかどうかは実装次第なので、flush()を明示的に呼んだ方が良いと思います。
Shane
大ベテラン
会議室デビュー日: 2003/06/06
投稿数: 132
お住まい・勤務地: Vancouver, BC
投稿日時: 2003-07-23 12:05
記憶がなくて具体例を出せなくて申し訳ないのですが、
実際に flush() しないで close() したときに
正常にデータが出力されなかった経験があります。
close() の前には flush() しておいた方が無難だと思います。
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2003-07-23 12:14
unibon です。

引用:

Cerberusさんの書き込み (2003-07-23 10:31) より:
しかしJDKのソースをのぞいたところ、close()内で自動的にflush()も呼ばれるようになっていました。
あえて上記のようにコーディングする理由はあるのでしょうか?



Java に限って言えば、PrintWriter のスーパクラスである Writer クラスで
close の際に flush すべきことが規定されているので、
close の前に flush を呼ぶ必要はないはずです。
http://java.sun.com/j2se/1.4/ja/docs/ja/api/java/io/Writer.html#close()
http://java.sun.com/j2se/1.4.2/docs/api/java/io/Writer.html#close()
#なお日本語訳は少し間違っているようです。

むしろ、呼ぶと冗長になりますので、呼ばないほうが良いです。
もちろん、flush が必要な場面があり、それがたまたま close の直前だった、
という場合は呼んでも構わないとは思います。
しかし、close の直前にやみくもに flush するのは、冗長でしょう。

ちなみに、Java 以外では C から使えるライブラリやシステムコールの中には、
close だけ呼ぶと flush してくれない、というのが過去にはいくつかありました
(記憶があいまいですが)。
マーフィーの法則のように、
flush があるのに close 前に flush を呼ばないとハマる、
のような伝説があるという位置づけで考えられればよいでしょう
(とにかく見えない危険を回避したければ呼べばよいし、
Writer クラスの規定を信じて冗長性を排除したいならば呼ばなくてもよい)。



#以下、後で追加。

すみません。長々と書いていたらカブってしまいました。
この投稿は削除扱いということで見てください(実際に削除はしませんが)。

[ メッセージ編集済み 編集者: unibon 編集日時 2003-07-23 12:37 ]
Cerberus
会議室デビュー日: 2003/07/23
投稿数: 2
お住まい・勤務地: 東京都
投稿日時: 2003-07-23 13:26
H2さん、Shinさん、unibonさん、返信ありがとうございます

PrintWriterがflushしてくれない場合があるというのを聞いたことがあったので調べていたら、以下のようなページを見つけました。

日本語訳
http://java.sun.com/j2se/1.4/ja/docs/ja/guide/io/troubleshooting.html
原文
http://java.sun.com/j2se/1.4.2/docs/guide/io/troubleshooting.html

一番下にあるこの行は、微妙な訳です。

引用:
PrintStream および PrintWriter オブジェクトでは、出力がフラッシュされないことがあります。 自動的にフラッシュするには、これらのクラスから 2 つの引数をとるコンストラクタを呼び出して、第 2 引数に true を指定します。

PrintStream and PrintWriter objects do not always flush their output. To arrange for automatic flushing, use the two-argument constructors of these classes and specify true for the second argument.



これだけ読むと、flushされないことがあるから、closeする前にflushしなきゃいけないような誤解を招きそうですね。
1

スキルアップ/キャリアアップ(JOB@IT)