読者です 読者をやめる 読者になる 読者になる

ファイル入出力 Bufferedな例

Oracle Technology Network for Java Developers | Oracle Technology Network | Oracleにはこうあります。

一般的に、Reader に対して読み込み要求が出されると、それに対応する基本となる文字型ストリームまたはバイトストリームへの読み込み要求が発行されます。このため、FileReader や InputStreamReader のように read() オペレーションの効率の良くない Reader では、その周りを BufferedReader でラップすることをお勧めします。次に例を示します。

BufferedReader in
= new BufferedReader(new FileReader("foo.in"));

この例は指定されたファイルからの入力をバッファーします。バッファリングせずに read()、readLine() を使うと、呼び出しごとにファイルからバイトを読み込み、文字型に変換し、そのたびに復帰するので、非常に効率が悪くなります。

ちなみにReader,Writerクラスを継承するサブクラス達はBuilderパターンというデザインパターンで設計されています。
参考:http://www.coppermine.jp/hasunuma/weblog/2010/07/java-api---builder.html
Builderパターンなのでメソッドの変更も簡単です。
[ファイル出力メソッド]

public static void write(String fileName, String data){
    Writer writer = null;
    try{
        writer = new BufferedWriter(new FileWriter(fileName));
        writer.write(data);
    }catch (IOException e) {
        e.printStackTrace();
    }finally{
        if(writer != null){
            try {
                writer.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

[ファイル読込メソッド]

public static String read(String fileName){
    Reader reader = null;
    StringBuffer str = new StringBuffer();
    try{
        reader = new BufferedReader(new FileReader(fileName));
        int offset = 0, length = 1024, bufsize = 0;
        char cbuf[] = new char[length];
        while((bufsize = reader.read(cbuf, offset, length)) != -1){
            str.append(cbuf,offset,bufsize);
            cbuf = new char[length];
        }
    }catch (IOException e) {
        e.printStackTrace();
    }finally{
        if(reader != null){
            try {
                reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    return str.toString();
}

■解説
シンプルな例(ファイル入出力 シンプルな例 - clash_m45の開発日記)と比較すると、違いは

writer = new BufferedWriter(new FileWriter(fileName));
reader = new BufferedReader(new FileReader(fileName));

だけです。

■FileReader+FileWriter(シンプルな例)と今回の例での処理速度測定結果
こんなTestCaseを作って処理速度を測ってみた。

テストデータは5.2Mのファイルです。

public class FileSpeedTest extends TestCase {

    private String inFileName = "resources/file/dummy.dat";
    private String outFileName = "tmp/dummy.dat";

    private long start;
    private long end;

    @Override
    public void setUp(){
        start = System.currentTimeMillis();
    }
    @Override
    public void tearDown(){
        end = System.currentTimeMillis();
        System.out.println(end-start+"ms.");
    }

    public void testSimple(){
        String data = SimpleFileInOut.read(inFileName);
        SimpleFileInOut.write(outFileName,data);
    }

    public void testBuffered(){
        String data = BufferedFileInOut.read(inFileName);
        BufferedFileInOut.write(outFileName,data);
    }
}

testSimple : 235ms.
testBuffered : 205ms.

少しだけBufferedを使ったほうが早いようですね。