JavaのBufferedOutputStreamクラスの使い方を解説!flushメソッドでデータを確実に出力しよう
生徒
「Javaでファイルに書き込む処理って、書いた内容がすぐに保存されるんですか?」
先生
「それが、すぐには保存されないこともあるんです。バッファにたまっているだけで、実際のファイルに書き込まれていない場合があります。」
生徒
「えっ、それって困りませんか?書いたのに消えちゃうとか…」
先生
「そこで使うのがBufferedOutputStreamのflushメソッドです。これを使えば、バッファにたまっているデータをすぐに出力先へ書き出せるんですよ。今日はこの使い方を学びましょう!」
1. BufferedOutputStreamクラスとは
BufferedOutputStreamは、Javaでデータを書き込むときに使う出力用ストリームのひとつで、バッファを使って処理の効率を高める仕組みを持っています。
ファイルなどにデータを書き込むとき、1バイトずつ直接書くと効率が悪くなります。BufferedOutputStreamは、データをいったんバッファにためてからまとめて書き込むことで、出力処理の速度を改善してくれます。
2. flushメソッドとは?
flushメソッドは、BufferedOutputStreamなどの出力ストリームで使われるメソッドで、「バッファにたまっているデータをすぐに書き出す」ために使います。
たとえば、バッファがいっぱいになる前にプログラムが終了した場合、flushを使っていないと、書き込み内容が出力先(ファイルなど)に保存されないまま終わってしまう可能性があります。flushは「確実に保存する」ための重要な操作です。
3. flushメソッドの基本的な使い方
それでは、実際にBufferedOutputStreamでファイルに文字列を書き込んで、flushで内容を出力する基本的なサンプルを見てみましょう。
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class FlushExample {
public static void main(String[] args) {
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("output.txt"))) {
String message = "こんにちは、Java!";
bos.write(message.getBytes()); // バッファに書き込み
bos.flush(); // バッファの内容をファイルに出力
} catch (IOException e) {
e.printStackTrace();
}
}
}
output.txt に「こんにちは、Java!」という内容が保存される
このようにwriteメソッドで書き込んだあと、flushメソッドを呼び出すことで、データが実際にファイルへ書き出されます。
4. flushが必要な理由
なぜflushが必要なのかというと、BufferedOutputStreamは性能を上げるために「すぐに書き出さずにためておく」仕組みになっているからです。バッファサイズを超えるまで書き出しを遅らせるので、少量のデータだけを書いたまま終了すると、ファイルに書き込まれないまま終わることがあります。
そのため、書き込みが完了したら必ずflushを呼ぶようにするのが安全な書き方です。
5. flushとcloseの違い
flushメソッドは「バッファの中身を出力先へ書き出す」だけですが、closeメソッドは「書き出してからストリームを閉じる」操作です。
closeを呼べば内部的にflushも実行されますが、ストリームを閉じたあとに再利用することはできません。逆にflushだけであれば、書き出したあとも引き続きwriteを使ってデータを書き込むことができます。
6. flushはこんな場面で便利!
flushメソッドは次のような場面で活躍します。
- プログラムの途中で何度もバッファの内容を保存したいとき
- 重要なログやメッセージを即座にファイルへ書き出したいとき
- 書き込み後すぐに他のプロセスでファイルを読み取る必要があるとき
たとえばログ出力では、flushを使っておかないとログが残らず、問題発生時に原因調査ができなくなることがあります。
7. BufferedOutputStreamとflushを安全に使うには?
flushを使っていても、ストリームを確実に閉じることはとても重要です。Java7以降では、try-with-resources構文を使えば自動的にcloseが呼ばれ、flushも確実に実行されます。
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("data.txt"))) {
bos.write("データ".getBytes());
// flushは不要でもclose時に自動で実行される
}
このようにしておけば、flushの呼び忘れによるデータ損失を防ぐことができます。