EeBlog(テクニカルブログ)

第105回 ファイルチャンネルの入出力

引き続き「ファイルチャンネルの入出力」について見ていきます。

前回はFileInputStreamのgetChannelメソッドによりFileChannelを取得しましたが、これは読み込み専用のFileChannelです。
書き込み専用のFileChannelはFileOutputStreamのgetChannelメソッドで取得できます。

FileChannelはバイトを書き込むためのWritableByteChannel インターフェース、GatheringByteChannelインターフェースを実装しており、これらのwriteメソッドを実行すると、現在位置(position)からバイトを書き込みます。
ただし、追加モードでは、現在位置をファイルの末尾に設定してからバイトを書き込みます。
また、現在位置は書き込まれた分だけ移動します。


次のプログラムの実行によりチャンネル取得時とwriteメソッド実行直後のpositionの値を確認します。
追加モードで同じ文字列を10行書き込みます。

 import java.io.FileOutputStream;
 import java.nio.ByteBuffer;
 import java.nio.channels.FileChannel;


 public class Main {


     private static final String LINE_SEPARATOR 
                                  = System.getProperty("line.separator");
     private static final String DATA = "株式会社イーブ" + LINE_SEPARATOR;
     private static final byte[] BYTE_DATA = DATA.getBytes();
     private static final String MESSAGE_FORMAT 
                          = "position:%1$d  size:%2$d" + LINE_SEPARATOR;


     public static void main(String[] strings) {
         FileChannel fileChannel = null;
         try {
             FileOutputStream fileOutputStream 
                            = new FileOutputStream("output.txt", true);
             fileChannel = fileOutputStream.getChannel();
             messageOut(fileChannel);
             ByteBuffer byteBuffer = ByteBuffer.wrap(BYTE_DATA);
             for (int i = 0; i < 10; i++) {
                 fileChannel.write(byteBuffer);
                 messageOut(fileChannel);
                 byteBuffer.rewind();
             }
         } catch (Exception e) {
             e.printStackTrace();
         } finally {
             try {
                 fileChannel.close();
             } catch (Exception e) {}
         }
     }


     private static void messageOut(FileChannel fileChannel) throws Exception {
         System.out.printf(MESSAGE_FORMAT, fileChannel.position()
                                         , fileChannel.size());
     }
 }

実行すると次のように表示されます。
position:0 size:672
position:688 size:688
position:704 size:704
position:720 size:720
position:736 size:736
position:752 size:752
position:768 size:768
position:784 size:784
position:800 size:800
position:816 size:816
position:832 size:832

ちなみに、FileChannelクラスにはチャネルの現在位置に影響を及ぼすことなく、ファイル内の絶対位置から書き込むwriteメソッドも存在します。(sizeは影響を受けます。)