Java ファイルコピー(バッファサイズを変更)
Java で java.io.InputStream、java.io.OutputStream での
入出力ストリームを利用したコピー処理を行うサンプルプログラムを紹介します。
ストリームを利用したコピー処理では、読み込みバファサイズを大きくすることで、大きなファイルでも比較的高速にコピーを行えます。
サンプルプログラムではデータの読み込みバッファーサイズを引数で指定可能としています。
指定した読み込みバファ領域はJavaVMのヒープ内に確保されますので、あまり大きくしすぎても効率が悪くなります。そのため、ファイルをコピーする上で、効率の良いデータ読み込みバッファサイズについても同時に確認します。
サンプルプログラム
/**
* 入力ストリームから出力ストリームへデータの書き込みを行います。
* 尚、コピー処理終了後、入力・出力ストリームを閉じます。
* @param in 入力ストリーム
* @param os 出力ストリーム
* @param bufferSize データの読み込みバッファサイズ(KB)です。
* @throws IOException 何らかの入出力処理例外が発生した場合
*/
public static void copyStream(InputStream in, OutputStream os,
int bufferSize) throws IOException {
int len = -1;
byte[] b = new byte[bufferSize * 1024];
try {
while ((len = in.read(b, 0, b.length)) != -1) {
os.write(b, 0, len);
}
os.flush();
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
実行
サンプルプログラムのファイルコピーを行うために、Cドライブ直下に 100MB のファイル「100M.txt」を用意しました。サンプルプログラムでは、 C:\100M.txt を、バッファサイズ 1000KB 単位でデータを読み込み C:\a.txt にコピーします。
尚、サンプルの実行は以下の環境で行いました。
OS : WindowsXP
CPU : Athlon 1.46GHz
メモリー : 1GB
JRE : 1.6.4
◆実行例
/** * 実行例 * @param args */ public static void main(String[] args) { try { copyStream("C:\\100M.txt", "C:\\a.txt",1000); } catch (IOException e) { e.printStackTrace(); } }
バッファサイズの変更
ファイルをコピーする上で、効率の良いデータ読み込みバッファサイズを確認するため、copyStream の第3引数に
1KB、100KB、1000KB、10000KB単位で同様のコピー処理を行った結果を以下にまとめています。
上記の結果だけで断定することはできませんが、データ読み込みバッファサイズを 1000KB 単位に指定すると、
コピー処理中のヒープ使用量、処理時間において効率が良いと言う結果が出ました。
尚、ファイルサイズを大きくした場合( 1GB 程度)でも同様の結果が得られました。
逆にサイズが小さいファイル( 1MB 以下ぐらい )をコピーする場合は、バッファサイズを大きくしても無駄になりますので 100KB ぐらいで指定するのが良いかと思います。
FileChannelを利用してもっと高速に
java.io.InputStream、java.io.OutputStream
でのコピー処理は入出力ストリームを理解する上で、重要ではありますが、
J2SE1.4 で導入された New I/O の java.nio.channels.FileChannel#transferTo
メソッドを利用することで、さらに効率良くファイルコピーを行うことができます。
次は、FileChannel を利用して簡単・高速にファイルコピーを行う方法を紹介します。
⇒ Java ファイルコピー(簡単・高速)