transferFrom/transferToによる2GBを超えるファイルのコピーで嵌められる
久々に書いてみる。
Javaでファイルをコピーするには、java.nioのtransferFrom/transferToを使うと早いとされていますが、そこには落とし穴が。
だいたい、どんなサイトでも以下のようなサンプルが載っています。
FileChannel src = new FileInputStream(source).getChannel();
FileChannel dst = new FileOutputStream(destination).getChannel();
dst.transferFrom(src, 0, src.size());
dst.close();
src.close();
が、これがダメなんだな。
以下のようにしないと、不完全なコピーが出来上がることがある。
FileChannel src = new FileInputStream(source).getChannel();
FileChannel dst = new FileOutputStream(destination).getChannel();
long pos = 0;
long size = src .size();
while (pos < size) {
long add = src .transferTo(pos, size, dst);
if (add == 0) {
throw new IOException();
}
pos += add;
}
dst.close();
src.close();
そう、1回でコピーしきれないことがある。それが2G超のファイルで顕著に表れる。
(JVMの実装依存だとは思うんだが。)
単純にStreamをwhileで回すだけだと問題は起きないので、高速化しようとして陥る罠ってところですな。