- - PR -
write()メソッドについて
1
投稿者 | 投稿内容 | ||||||||
---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2006-05-16 18:17
初心者ですが、宜しくお願いします。
FileWriter fw = new FileWriter(ファイルのパス); fw.write(書き出す文字列); このwrite()メソッドについて質問があります。 FileWriterは出力のキャラクターストリームであるため、 BufferedWriterのようにバッファリングをして書き込むのではなく 一文字ずつファイルにアクセスし書き込まれるのではないのですか? にもかかわらず、fw.flush()などをつかってフラッシュしないとファイルに 書き込まれないのは、FileWriterもバッファリングして書き込んでるのでしょうか? FileWriterはバッファリングをしないものだと教わったので良く分かりません。 ご教授お願いします。 | ||||||||
|
投稿日時: 2006-05-16 18:42
FileWriterはOutputStreamWriterを拡張しています。
http://java.sun.com/j2se/1.5.0/ja/docs/ja/api/java/io/OutputStreamWriter.html ここに書いてあるとおり、基本となる出力ストリーム(FileOutputStream)に対しては バッファリングされて出力されますが、これはOutputStreamWriterのバッファではなく、 エンコーディングコンバータ側のものです。 write()する度にFileOutputStreamに出力されるわけではありませんが、 エンコーディングコンバータへの出力がwrite()の度に発生することを防ぐために BufferedWriterでラップした方が効率が良くなると書いてあります。 バッファ -> エンコーディングコンバータ -> バッファ -> ファイル このような二階層のバッファを使うことになるわけです。 | ||||||||
|
投稿日時: 2006-05-16 20:43
早速の回答ありがとうございます。
こんなに早く回答をもらえるとは思ってもいませんでした。 回答の内容、自分にとってはかなり高度なので、回答を基に調べながら意味するところを理解したいと思います。 ありがとう。 | ||||||||
|
投稿日時: 2006-05-16 22:09
それではもう少し踏み込んで、、、
Javaのキャラクタ(char)を、例えばUTF-8として出力したとすると、 1文字につき1〜3バイトがバイトストリームに出力されるわけです。 仮にエンコーディングコンバータにバッファに類するものが全くなかったと すると、3バイトの出力にバイトストリームのwrite()が3回呼ばれるわけです。 1文字出力するのに何回もwrite()を呼んだのではメソッド呼び出しや引数検査、 内部状態の検査等のオーバーヘッドが無駄にかかりすぎてしまうでしょう? もちろんそんなお粗末な実装にするわけはないので、最低1文字を出力するのに 必要な分のバッファが必要になりますし、確保するからにはもっと溜め込める ようにしても大差ないのでもっと大きく確保することになるわけです。 #エンコーディングによってはバッファ無しで実装できないものもあるかも? これがエンコーディングコンバータ側のバッファです。 FileWriterがバッファリングしないというのは、write()では何もせずに、 そのままエンコーディングコンバータに丸投げしている、という意味です。 エンコーディングコンバータも頻繁にwrite()されると、以前の変換状態の 検査等でオーバーヘッドがあるので、バッファするのがベターですよ、と。 まぁ、こちらが有効なのはwrite(int)で毎回1文字ずつ出力をするような 作りのプログラムくらいのものだとは思いますけど。 ちなみに、オーバーヘッドにも大小があって、FileOutputStreamの先は JNI経由でOSのシステムコール(もしくは類似品)が発生するので、 エンコーディング変換と較べるとこちらの方が遙かに大きいです。 | ||||||||
|
投稿日時: 2006-05-17 14:12
再度の詳しい回答ありがとうございます。
FileWriterは、エンコーディングコンバータ -> バッファ -> ファイル BufferedWriterは、バッファ -> エンコーディングコンバータ -> バッファ -> ファイル という解釈でいいのでしょうか。 エンコーディングコンバータという言葉も始めて聞き、学校の勉強の浅はかさを思いしらされました。。 ありがとうございました。 | ||||||||
|
投稿日時: 2006-05-17 14:28
気になったので自分なりに調べてみました。
まず、FileWriter は、すなわち FileWriter extends OutputStreamWriter ですが、 http://java.sun.com/j2se/1.5.0/ja/docs/ja/api/java/io/OutputStreamWriter.html によると、
とあります。このバッファーのサイズはコンストラクターの引数で指定された CharsetEncoder を介して指定することになると思います。 そして、CharsetEncoder は、 http://java.sun.com/j2se/1.5.0/ja/docs/ja/api/java/nio/charset/CharsetEncoder.html によると、
となっていて、新しい仕様です。 一方 OutputStreamWriter は 1.1 から登場したクラスです。 結局は、OutputStreamWriter のバッファーサイズというのは、内部的な実装の仕様であり、将来も変わりうるものではないでしょうか。だから、結局は FileWriter がバッファーをどう使っているかは現時点のバーションのソースコードを見ないことには分からない、というのが本当のところだと思います。 -- unibon {B73D0144-CD2A-11DA-8E06-0050DA15BC86} | ||||||||
|
投稿日時: 2006-05-17 22:35
違う方からも回答いただき感謝です。
質問内容が教科書的な内容で、回答の方も大変なのにありがとうでした。 | ||||||||
|
投稿日時: 2006-05-18 02:15
エンコーディング変換系のクラスが表に出たのはNIOが登場した1.4系からですが、 実際は内部的にはどのみち必要になるので、昔から実装上はあったと思いますよ。 #もちろん、仕様にはないので確かな話ではないですけどね。 |
1