ファイルのコピー処理各種


ストリームによるファイルコピー

シンプルなストリームによるファイルコピー

public static void copy(String src, String dest) throws IOException {
    InputStream in = null;
    OutputStream out = null;
    try {
        in = new BufferedInputStream(new FileInputStream(src));
        out = new BufferedOutputStream(new FileOutputStream(dest));
        byte[] buf = new byte[BUFFER_SIZE];
        int length;
        while (-1 < (length = in.read(buf))) {
            out.write(buf, 0, length);
            out.flush();
        }
    } finally {
        closeIgnoringException(in);
        closeIgnoringException(out);
    }
}

BUFFER_SIZE は 4096 とかプラットフォームに応じた値にする。


closeIgnoringException はヘルパーメソッドです。

private static void closeIgnoringException(Closeable closeable) {
    if (closeable != null) {
        try {
            closeable.close();
        } catch (IOException e) {
            // do nothing
        }
    }
}

ダイレクト・バッファー

ヒープ外にメモリが確保され、バッファー操作に高速なネイティブI/O操作が直接使用されます。ただしアロケートのコストが大きいため、長期的なバッファーへの使用が効果的です。

public static void directBufferCopy(String src, String dest) throws IOException {
    FileChannel srcChannel = null;
    FileChannel destChannel = null;
    try {
        srcChannel = new FileInputStream(src).getChannel();
        destChannel = new FileOutputStream(dest).getChannel();
        ByteBuffer buffer = ByteBuffer.allocateDirect(BUFFER_SIZE);
        while (srcChannel.read(buffer) > 0) {
            buffer.flip();
            destChannel.write(buffer);
            buffer.clear();
        }
    } finally {
        closeIgnoringException(srcChannel);
        closeIgnoringException(destChannel);
    }
}

トランスファ

チャネルからチャネルにバイトを転送します。

public static void transferCopy(String src, String dest) throws IOException {
    FileChannel srcChannel = null;
    FileChannel destChannel = null;
    try {
        srcChannel = new FileInputStream(src).getChannel();
        destChannel = new FileOutputStream(dest).getChannel();
        srcChannel.transferTo(0, srcChannel.size(), destChannel);
    } finally {
        closeIgnoringException(srcChannel);
        closeIgnoringException(destChannel);
    }
}

メモリー・マップ・ファイル

MappedByteBuffer を使ったファイルコピーの例です。MappedByteBuffer はファイルの一定の領域を直接メモリーにマップします。

public static void mappedCopy(String src, String dest) throws IOException {
    FileChannel srcChannel = null;
    FileChannel destChannel = null;
    try {
        srcChannel = new FileInputStream(src).getChannel();
        destChannel = new FileOutputStream(dest).getChannel();
        ByteBuffer srcBuffer = srcChannel.map(FileChannel.MapMode.READ_ONLY,
                                 0, srcChannel.size());
        destChannel.write(srcBuffer);
    } finally {
        closeIgnoringException(srcChannel);
        closeIgnoringException(destChannel);
    }
}

srcChannel.map()によるMappedByteBufferの作成は、srcChannel.size()によりサイズ指定をしてますが、大きくなる場合はファイルの一部分をマップして、分割して処理します。

ちなみに・・

ちなみに、ストリームを1つだけ使用する場合は、以下のように宣言と初期化を同時に行うことができます。前述までのように、2つのストリームを使う場合には2つ目の初期化が失敗した場合に、最初のストリームについてクローズ処理を行う必要があるため、初期化はtryブロック中に入れる必要があります。

    InputStream in = new BufferedInputStream(new FileInputStream(src));
    try {
        byte[] buf = new byte[BUFFER_SIZE];
        int length;
        while (-1 < (length = in.read(buf))) {
            ・・・
        }
    } finally {
        closeIgnoringException(in);
    }