在Java中复制文件的最快方法
在Java中复制大量文件的最快方法是什么。到目前为止,我已经使用了文件流和nio。总体而言,流似乎比nio更快。到目前为止,你有哪些经验 让java派生一个复制文件的操作系统批处理脚本。您的代码可能必须编写批处理脚本。我将使用:在Java中复制文件的最快方法,java,file-io,Java,File Io,在Java中复制大量文件的最快方法是什么。到目前为止,我已经使用了文件流和nio。总体而言,流似乎比nio更快。到目前为止,你有哪些经验 让java派生一个复制文件的操作系统批处理脚本。您的代码可能必须编写批处理脚本。我将使用: import java.io.*; import java.nio.channels.*; public class FileUtils{ public static void copyFile(File in, File out) thro
import java.io.*;
import java.nio.channels.*;
public class FileUtils{
public static void copyFile(File in, File out)
throws IOException
{
FileChannel inChannel = new
FileInputStream(in).getChannel();
FileChannel outChannel = new
FileOutputStream(out).getChannel();
try {
inChannel.transferTo(0, inChannel.size(),
outChannel);
}
catch (IOException e) {
throw e;
}
finally {
if (inChannel != null) inChannel.close();
if (outChannel != null) outChannel.close();
}
}
public static void main(String args[]) throws IOException{
FileUtils.copyFile(new File(args[0]),new File(args[1]));
}
}
如果您的任何文件在Windows中大于64M,您可能需要查看以下内容:
可能会给你答案
对于基准测试,我使用不同的文件进行了测试
您可以使用ApacheCommons io库的FileUtils实现来复制文件
FileUtils.copyFile(new File(sourcePath), new File(destPath));
它使用FileChannel进行IO操作
或使用
java.nio.file.Files
的copy()
方法。它依赖于文件(更大的文件),对我来说,这是使用缓冲流的最快方法
public void copyFile(File inFileStr, File outFileStr) throws IOException {
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(inFileStr));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(outFileStr))) {
byte[] buffer = new byte[1024 * 1024];
int read = 0;
while ((read = bis.read(buffer)) != -1) {
bos.write(buffer, 0, read);
}
bis.close();
bos.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
使用流
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();
}
}
使用频道
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();
}
}
使用Apache Commons IO
private static void copyFileUsingApacheCommonsIO(File source, File dest) throws IOException {
FileUtils.copyFile(source, dest);
}
使用Java SE 7文件
private static void copyFileUsingJava7Files(File source, File dest) throws IOException {
Files.copy(source.toPath(), dest.toPath());
}
性能测试
File source = new File("/Users/tmp/source.avi");
File dest = new File("/Users/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/tmp/sourceChannel.avi");
dest = new File("/Users/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/tmp/sourceApache.avi");
dest = new File("/Users/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/tmp/sourceJava7.avi");
dest = new File("/Users/tmp/destJava7.avi");
start = System.nanoTime();
copyFileUsingJava7Files(source, dest);
System.out.println("Time taken by Java7 Files Copy = "+(System.nanoTime()-start));
结果
Time taken by Stream Copy = 44,582,575,000
Time taken by Java7 Files Copy = 89,061,578,000
Time taken by Channel Copy = 104,138,195,000
Time taken by Apache Commons IO Copy = 108,396,714,000
您在复制文件时是否对其进行某种转换?为什么不直接使用操作系统的文件系统功能呢?不,我没有做任何转换。但是,复制10000多个文件时,错误处理会困难得多,复制小文件时生成系统线程的开销太大。我建议您修改您的问题,将我们发现的约束包括在内。您希望并行处理多少个?您尝试过tar管道吗?rsync?(Sys管理员可能会在这里提供帮助-可能是针对ServerFault)已经考虑过这一点,但是在复制10000多个文件时,错误处理将非常困难,并且在复制小文件时生成系统线程的开销非常大。此外,该应用程序不会独立于平台。无论如何,您都必须处理错误检查。2.你说得对,它不是平台独立的,所以你打算在不同类型的服务器上运行它?3.你能在“适当”的地方开始创建10000个文件而不需要任何副本吗?4.不要为每个文件生成一个线程。每100个文件就有一个线程,我同意这一点。哑拷贝文件不是Java的理想用例。如果您想从Java中执行,那么就进行操作系统级调用。catch(IOException e){throw e;}谢谢,这比我使用的要快得多!我的IDE警告我应该关闭InputStream而不是通道。。。对此有何评论?@basZero说,他们应该都能更好地粘贴此链接:)@Mak粘贴链接并不好,因为链接将来可能会死掉。例如:一个未被接受的答案中的oracle链接不再有效。