EeBlog(テクニカルブログ)

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

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

ByteBufferにはダイレクトバッファと非ダイレクトバッファがあります。
ダイレクトバッファを使った入出力は、中間バッファを介さずに行うため、非ダイレクトバッファよりも高速です。
ただし、非ダイレクトバッファよりも割り当ておよび解放コストが高く、寿命が長く容量の大きいバッファとして扱うのに適しています。

今回は、ファイルの領域をメモリに直接マッピングするMappedByteBufferというダイレクトバッファによるファイル入出力について見ていきます。


次のサンプルコードはMappedByteBufferを使用し、ファイルの入出力を行うプログラムです。
ただし、このサンプルコードはバッファの容量が小さいので、ダイレクトバッファを使用するのに適しているものではありません。

 import java.io.RandomAccessFile;
 import java.nio.MappedByteBuffer;
 import java.nio.channels.Channels;
 import java.nio.channels.FileChannel;
 import java.nio.channels.FileChannel.MapMode;


 public class Main {


     private static final String DATA = "株式会社イーブ";
     private static final byte[] BYTE_DATA = DATA.getBytes();


     public static void main(String[] args) {
         FileChannel fileChannel = null;
         try {
             RandomAccessFile randomAccessFile 
                              = new RandomAccessFile("output.txt", "rw");
             fileChannel = randomAccessFile.getChannel();
             MappedByteBuffer mappedByteBuffer 
               = fileChannel.map(MapMode.READ_WRITE, 0, BYTE_DATA.length);
             Channels.newChannel(System.out).write(mappedByteBuffer);
             mappedByteBuffer.clear();
             mappedByteBuffer.put(BYTE_DATA);
             mappedByteBuffer.force();
         } catch (Exception e) {
             e.printStackTrace();
         } finally {
             try {
                 fileChannel.close();
             } catch (Exception e) {}
         }
     }
 }

MappedByteBufferはFileChannelのmapメソッドにより取得します。
第一引数はマッピングのモードを指定します。
READ_ONLYを指定すると、バッファは読み込み専用になります。
READ_WRITEを指定すると、バッファは読み書き可能となり、変更がファイルに反映されます。
PRIVATEを指定すると、バッファは読み書き可能となりますが、変更はファイルに反映されません。

今回は読み書きを行うため、RandomAccessFileからFileChannelを取得しました。
MappedByteBufferはByteBufferを継承しているので、ByteBufferと同じように扱えます。
putメソッドによりバッファの内容を変更し、forceメソッドでその変更をファイルに書き込んでいます。