欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java IO进行文件copy

程序员文章站 2022-06-16 20:06:17
...

此处列举四种copy方式(不考虑复制时重复的冲突),其中前三种需要递归复制,第四种使用ApacheCommonsIO工具类,不需要自己手写递归。
递归复制

/**
  * 递归复制
  * @param file  原文件路径
  * @param copyFile  复制文件路径
  * @param type  复制方式
  * @throws IOException
  */
public static void copy(File file, File copyFile, int type) throws IOException {
        if (file.isDirectory()) {
            if (!copyFile.exists()) {
                copyFile.mkdir();
            }
            File[] fileList = file.listFiles();
            for (File file1 : fileList) {
                copy(file1,new File(copyFile.getPath()+File.separator+file1.getName()),type);
            }
        } else {
            switch (type) {
                case 1:
                    one(file, copyFile);
                    break;
                case 2:
                    two(file, copyFile);
                    break;
                case 3:
                    Files.copy(file.toPath(),copyFile.toPath());
                    break;
            }

        }
}

方式一:传统流复制(需递归调用)

public static void one(File file, File copyFile) throws IOException {

    FileInputStream src = new FileInputStream(file);
    FileOutputStream desc = new FileOutputStream(copyFile);

    byte[] buf = new byte[1024 * 10];
    int len = -1;
    while ((len = src.read(buf)) != -1) {
        desc.write(buf, 0, len);
    }

    src.close();
    desc.close();
}

方式二:Channel通道方式(需递归调用)

public static void two(File file, File copyFile) throws IOException {

    FileInputStream fis = new FileInputStream(file);
    FileOutputStream fos = new FileOutputStream(copyFile);

    FileChannel in = fis.getChannel();
    FileChannel out = fos.getChannel();
    in.transferTo(0,in.size(),out);

    in.close();
    out.close();
    src.close();
    desc.close();
}

方式三:NIO的Files.copy方法(需递归调用)

Files.copy(file.toPath(),copyFile.toPath());

方式四:ApacheCommonsIO工具类(一句代码直接搞定,很省事)

FileUtils.copyDirectory(file4,copyFile4);

下面是完整代码,此处使用了四个相同文件分别复制,用来测试每个复制所用耗时。测试文件为项目源代码,大概5000+文件,大小60M左右。

package com.mosen;

import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.nio.file.Files;

/**
 * Created by Mosen on 2017/8/15.
 */
public class Copy {

    public static void main(String[] args) throws IOException {
        File file1 = new File("C:\\Users\\Mosen\\Desktop\\copyTest\\FileTest1");
        File copyFile1 = new File("C:\\Users\\Mosen\\Desktop\\copyTest\\FileTestCopy1");
        long start = System.currentTimeMillis();
        copy(file1,copyFile1,1);  //方式1,传统方式
        long end = System.currentTimeMillis();
        System.out.println("方式1复制完毕!耗时:" + (end - start) + "ms");

        File file2 = new File("C:\\Users\\Mosen\\Desktop\\copyTest\\FileTest2");
        File copyFile2 = new File("C:\\Users\\Mosen\\Desktop\\copyTest\\FileTestCopy2");
        start = System.currentTimeMillis();
        copy(file2,copyFile2,2);  //方式2,Channel通道方式
        end = System.currentTimeMillis();
        System.out.println("方式2复制完毕!耗时:" + (end - start) + "ms");

        File file3 = new File("C:\\Users\\Mosen\\Desktop\\copyTest\\FileTest3");
        File copyFile3 = new File("C:\\Users\\Mosen\\Desktop\\copyTest\\FileTestCopy3");
        start = System.currentTimeMillis();
        copy(file3,copyFile3,3);  //方式3,NIO的Files.copy方式
        end = System.currentTimeMillis();
        System.out.println("方式3复制完毕!耗时:" + (end - start) + "ms");

        File file4 = new File("C:\\Users\\Mosen\\Desktop\\copyTest\\FileTest4");
        File copyFile4 = new File("C:\\Users\\Mosen\\Desktop\\copyTest\\FileTestCopy4");
        start = System.currentTimeMillis();
        FileUtils.copyDirectory(file4,copyFile4);
        end = System.currentTimeMillis();   //方式4,Apache Commons 工具类的方式
        System.out.println("方式4复制完毕!耗时:" + (end - start) + "ms");

    }

    /**
     * 递归复制
     * @param file  原文件路径
     * @param copyFile  复制文件路径
     * @param type  复制方式
     * @throws IOException
     */
    public static void copy(File file, File copyFile, int type) throws IOException {
        if (file.isDirectory()) {
            if (!copyFile.exists()) {
                copyFile.mkdir();
            }
            File[] fileList = file.listFiles();
            for (File file1 : fileList) {
                copy(file1,new File(copyFile.getPath()+File.separator+file1.getName()),type);
            }
        } else {
            switch (type) {
                case 1:
                    one(file, copyFile);
                    break;
                case 2:
                    two(file, copyFile);
                    break;
                case 3:
                    Files.copy(file.toPath(),copyFile.toPath());
                    break;
            }

        }
    }

    /**
     * 传统方式复制(文件,非文件夹)
     * @param file  原文件路径
     * @param copyFile  复制文件路径
     * @throws IOException
     */
    public static void one(File file, File copyFile) throws IOException {

        FileInputStream src = new FileInputStream(file);
        FileOutputStream desc = new FileOutputStream(copyFile);

        byte[] buf = new byte[1024 * 10];
        int len = -1;
        while ((len = src.read(buf)) != -1) {
            desc.write(buf, 0, len);
        }

        src.close();
        desc.close();
    }


    /**
     * 通道方式复制(文件,非文件夹)
     * @param file  原文件路径
     * @param copyFile  复制文件路径
     * @throws IOException
     */
    public static void two(File file, File copyFile) throws IOException {

        FileInputStream src = new FileInputStream(file);
        FileOutputStream desc = new FileOutputStream(copyFile);

        //通道方式
        FileChannel in = src.getChannel();
        FileChannel out = desc.getChannel();
        in.transferTo(0,in.size(),out);

        in.close();
        out.close();
        src.close();
        desc.close();
    }
}

测试结果

方式1复制完毕!耗时:18067ms      //传统流方式
方式2复制完毕!耗时:12856ms      //channel通道方式
方式3复制完毕!耗时:17840ms      //NIO的Files.copy方式
方式4复制完毕!耗时:23773ms      //ApacheCommonsIO工具类方式

在Windows上直接拖拽复制大约20s左右。
总的来说,复制还是channel通道方式最快。