Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/325.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java中复制文件的最快方法_Java_File Io - Fatal编程技术网

在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

在Java中复制大量文件的最快方法是什么。到目前为止,我已经使用了文件流和nio。总体而言,流似乎比nio更快。到目前为止,你有哪些经验

让java派生一个复制文件的操作系统批处理脚本。您的代码可能必须编写批处理脚本。

我将使用:

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,您可能需要查看以下内容: 可能会给你答案

对于基准测试,我使用不同的文件进行了测试

  • 小文件(5 KB)
  • 中等文件(50KB)
  • 大文件(5 MB)
  • Fat文件(50MB)
  • 和一个巨大的文件(1.3 GB)的二进制文件
  • 我先用文本文件做测试,然后用二进制文件。我在三种模式下进行了测试:

  • 在同一硬盘上。它是一个250 GB的IDE硬盘,有8 MB的缓存。它的格式是Ext4
  • 在两个磁盘之间。我使用了第一个磁盘和另一个250 GB的SATA硬盘,带有16 MB的缓存。它的格式是Ext4
  • 在两个磁盘之间。我使用了第一个磁盘和另一个SATA硬盘,容量为1 TB,缓存容量为32 MB。它是用NTFS格式化的
  • 我使用了一个基准框架,对所有方法进行了测试。这些测试是在我的个人电脑上进行的(Ubuntu 10.04 64位,Intel Core 2 Duo 3.16 GHz,6 Go DDR2,SATA硬盘)。使用的Java版本是Java 7 64位虚拟机


    您可以使用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链接不再有效。