Javaでファイルをコピーする方法は4つあります。
Javaのファイルコピーは非常に一般的な操作です。しかし、java.io.Fileクラスにはファイルをソースから宛先にコピーするためのショートカットメソッドは存在しません。ここでは、Javaでファイルをコピーするための4つの異なる方法について学びます。
Javaファイルのコピー
- Java コピー ファイル – ストリーム
これはJavaでのファイルコピーの一般的な方法です。ここでは、ソースと宛先の2つのファイルを作成します。次に、ソースからInputStreamを作成し、Javaのファイルコピー操作に使用するためにOutputStreamを使用して宛先ファイルに書き込みます。ストリームを使用してJavaでファイルをコピーするために使用できるメソッドは次のとおりです。
private static void copyFileUsingStream(File source, File dest) throws IOException {
InputStream is = null;
OutputStream os = null;
try {
is = new FileInputStream(source);
os = new FileOutputStream(dest);
byte[] buffer = new byte[1024];
int length;
while ((length = is.read(buffer)) > 0) {
os.write(buffer, 0, length);
}
} finally {
is.close();
os.close();
}
}
- Java のファイルコピー – java.nio.channels.FileChannel
Java NIOクラスはJava 1.4で導入され、FileChannelを使用してファイルをコピーすることができます。transferFrom()メソッドのjavadocによると、この方法は、Javaでファイルをコピーするためのストリームよりも速くなるはずです。以下に、FileChannelを使用してファイルをコピーするためのメソッドがあります。
private static void copyFileUsingChannel(File source, File dest) throws IOException {
FileChannel sourceChannel = null;
FileChannel destChannel = null;
try {
sourceChannel = new FileInputStream(source).getChannel();
destChannel = new FileOutputStream(dest).getChannel();
destChannel.transferFrom(sourceChannel, 0, sourceChannel.size());
}finally{
sourceChannel.close();
destChannel.close();
}
}
- Java コピー ファイル – Apache Commons IO FileUtils
Apache Commons IOのFileUtils.copyFile(File srcFile, File destFile)メソッドは、Javaでファイルをコピーするために使用することができます。既にApache Commons IOをプロジェクトで使用している場合は、コードのシンプルさのためにこのメソッドを使用することは理にかなっています。内部的にはJava NIOのFileChannelを使用しているため、他の機能で既に使用していない場合は、このラッパーメソッドを避けることができます。以下は、JavaでファイルをコピーするためにApache Commons IOを使用する方法です。
private static void copyFileUsingApacheCommonsIO(File source, File dest) throws IOException {
FileUtils.copyFile(source, dest);
}
- Javaのファイルコピー – Filesクラス
もしJava 7以上で作業している場合は、JavaでファイルをコピーするためにFilesクラスのcopy()メソッドを使用することができます。これはファイルシステムのプロバイダを使用してファイルをコピーします。
private static void copyFileUsingJava7Files(File source, File dest) throws IOException {
Files.copy(source.toPath(), dest.toPath());
}
最速の方法を見つけるために、1GBのファイルをコピーするテストクラスを作成し、上記の方法を一つずつ実行しました。各呼び出しでは、キャッシュの影響を避けるために異なるファイルを使用しました。
package com.scdev.files;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import org.apache.commons.io.FileUtils;
public class JavaCopyFile {
public static void main(String[] args) throws InterruptedException, IOException {
File source = new File("/Users/scdev/tmp/source.avi");
File dest = new File("/Users/scdev/tmp/dest.avi");
//copy file conventional way using Stream
long start = System.nanoTime();
copyFileUsingStream(source, dest);
System.out.println("Time taken by Stream Copy = "+(System.nanoTime()-start));
//copy files using java.nio FileChannel
source = new File("/Users/scdev/tmp/sourceChannel.avi");
dest = new File("/Users/scdev/tmp/destChannel.avi");
start = System.nanoTime();
copyFileUsingChannel(source, dest);
System.out.println("Time taken by Channel Copy = "+(System.nanoTime()-start));
//copy files using apache commons io
source = new File("/Users/scdev/tmp/sourceApache.avi");
dest = new File("/Users/scdev/tmp/destApache.avi");
start = System.nanoTime();
copyFileUsingApacheCommonsIO(source, dest);
System.out.println("Time taken by Apache Commons IO Copy = "+(System.nanoTime()-start));
//using Java 7 Files class
source = new File("/Users/scdev/tmp/sourceJava7.avi");
dest = new File("/Users/scdev/tmp/destJava7.avi");
start = System.nanoTime();
copyFileUsingJava7Files(source, dest);
System.out.println("Time taken by Java7 Files Copy = "+(System.nanoTime()-start));
}
}
上記のプログラムの出力です。Javaファイルのコピー操作には常に1つのメソッドしか使用しないように、上記のコードにコメントを追加しました。
Time taken by Stream Copy = 44582575000
Time taken by Channel Copy = 104138195000
Time taken by Apache Commons IO Copy = 108396714000
Time taken by Java7 Files Copy = 89061578000
出力から明らかに、Javaでファイルをコピーする最良の方法は「Stream Copy」です。ただし、これは非常に基本的なテストです。もしパフォーマンスに集中したプロジェクトに取り組んでいる場合は、異なる方法を試して、タイミングを記録してプロジェクトに最適なアプローチを見つけるべきです。また、ファイルの平均サイズに基づいて、異なる方法でJavaのファイルコピーを試すこともおすすめします。Javaでファイルをコピーする4つの方法についてYouTubeのビデオを作成しましたので、興味があればご覧ください。https://www.youtube.com/watch?v=op6tgG95zek