CLOVER🍀

That was when it all began.

Files#newInputStream、newOutputStreamって、バッファリングされてるんでしたっけ?

使おうとしてたまに気になって、調べて…を繰り返している気がするので、メモ。

Java 7で追加されたNIO.2の中に、Filesというクラスがあります。この中に、newBufferedReader/newBufferedWriterや、newInputStream/newOutputStreamというメソッドがあり、便利になりました感がありますよね。

ところで、InputStream/OutputStreamの方には「Buffered」が付いていないですよね。メソッド名から考えるとバッファリングされていなさそうですが、どうなのでしょうか?

ちなみに、Reader/Writerの方は戻り値の型がBufferedReader/BufferedWriterですが、InputStream/OutputStreamはバッファリングされていない型になっています。

で、ものは試しとプログラムを用意。ここで、「hello.txt」はすでに存在するファイルとします。
FilesStream.java

import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class FilesStream {
    public static void main(String... args) throws IOException {
        try (InputStream is = Files.newInputStream(Paths.get("hello.txt"));
             OutputStream os = Files.newOutputStream(Paths.get("hello-copy.txt"))) {
             int b = 0;

             while ((b = is.read()) != -1) {
                 os.write(b);
             }
        }
    }
}

これ、普通に動作しますが途中でちょっとデバッグコードを仕込んでみましょう。

             System.out.printf("InputStream class = %s%n", is.getClass().getName());
             System.out.printf("OutputStream class = %s%n", os.getClass().getName());

実行すると、こんな結果が出力されます。

InputStream class = sun.nio.ch.ChannelInputStream
OutputStream class = java.nio.channels.Channels$1

あ、動作させているのは、Oracle JDK 8です。

OutputStreamの方が、わかりやすそうですね。OutpuStreamは、java.nio.channels.Channelsで作成されている内部クラスのようです。ここで、Channels#newOutputStreamの説明は

結果として得られるストリームのwriteメソッドは、基本となるチャネルが非ブロック・モードである場合に呼び出されると、IllegalBlockingModeExceptionをスローします。ストリームはバッファに書き込まれません。ストリームは複数の並行スレッドからのアクセスに対して安全です。ストリームをクローズするとチャネルもクローズします。

なので、バッファリングされていないで正解のようです。

sun.nio.ch.ChannelInputStreamの方も、同様な感じっぽいですね。

いくつか調べてもみましたが、一応正しそうです。

http://docs.oracle.com/cd/E26537_01/tutorial/essential/io/file.html
http://tamanmohamed.blogspot.jp/2012/05/jdk7-using-buffered-io-for-files-in.html
http://www.c-jump.com/bcc/c257c/Week11/W11_0240_example_bufferedoutp.htm

あとは、バッファリングを入れるかどうかは使い方次第ということで。