内容学习于:edu.aliyun.com


文件拷贝功能

  在操作系统里面有一个copy命令,这个命令的主要功能是可以实现文件的拷贝处理,现在要求模拟这个命令,通过初始化参数输入拷贝的源文件路径与拷贝的目标路径实现文件的拷贝处理。

  需求分析:

  •   需要实现文件的拷贝操作,那么这种拷贝就有可能拷贝各种类型的文件,所以肯定使用字节流;
  •   在进行拷贝的时候有可能需要考虑到大文件的拷贝问题;
    实现方案:
<dl> <dt> 方案一:使用InputStream将全部要拷贝的内容直接读取到程序里面,而后一次性的输出到目标文件; </dt> <dd> 如果现在拷贝的文件很大,基本上程序就死了; </dd> <dt> 方案二:采用部分拷贝,读取一部分输出一部分数据,如果现在要采用第二种做法,核心的操作方法: </dt> <dd> InputStream: public int read(byte[] b) throws IOException; </dd> <dd> OutputStream: public void write(byte[] b, int off, int len) throws IOException。 </dd> </dl>

实现文件的拷贝代码:

public class JavaAPIDemo {
    public static void main(String[] args) throws Exception {
        if (args.length < 2) {
            System.out.println("请输入正确的参数");
            System.exit(1);//退出系统
        }
        long start = System.currentTimeMillis();
        FileUtil util = new FileUtil(args[0], args[1]);
        System.out.println(util.copy() ? "文件拷贝成功" : "文件拷贝失败");
        long end = System.currentTimeMillis();
        System.out.println("拷贝完成时间:" + (end - start) + "ms");
    }

}


class FileUtil {
    private File srcFile;
    private File decFile;

    public FileUtil(String srcFile, String decFile) {
        this(new File(srcFile), new File(decFile));
    }

    public FileUtil(File srcFile, File decFile) {//初始化
        this.srcFile = srcFile;
        this.decFile = decFile;
    }

    public boolean copy() throws Exception {//拷贝操作
        if (!srcFile.exists()) {//判断源文件是否存在
            System.out.println("源文件不存在");
            return false;
        }

        if (!decFile.getParentFile().exists()) {//判断父目录是否存在
            decFile.getParentFile().mkdirs();//创建父目录
        }
        InputStream in = null;
        OutputStream out = null;
        try {
            in = new FileInputStream(this.srcFile);
            out = new FileOutputStream(this.decFile);
            byte data[] = new byte[1024];//建立数据缓冲区
            int len = 0;//每次数据读取的长度
            while ((len = in.read(data)) != -1) {
                out.write(data, 0, len);//将每次读取出来的数据存入目标文件
            }
        } catch (Exception e) {
            throw e;
        } finally {//必须关闭
            if (in != null) {
                in.close();
            }
            if (out != null) {
                out.close();
            }
        }
        
        return true;
    }

}

结果:

文件拷贝成功
拷贝完成时间:9ms

  但是需要注意的是,以上的做法是属于文件拷贝的最原始实现,而从JDK 1.9 开始InputStream和Reader类中都追加有数据
转存的处理操作方法:

  • 【jdk1.9】InputStream: public long transferTo(OutputStream out) throws IOException
  • 【jdk1.10】Reader: public long transferTo(Writer out) throws IOException

转存功能

代码:

public class JavaAPIDemo {
    public static void main(String[] args) throws Exception {
        if (args.length < 2) {
            System.out.println("请输入正确的参数");
            System.exit(1);//退出系统
        }
        long start = System.currentTimeMillis();
        FileUtil util = new FileUtil(args[0], args[1]);
        System.out.println(util.copy() ? "文件拷贝成功" : "文件拷贝失败");
        long end = System.currentTimeMillis();
        System.out.println("拷贝完成时间:" + (end - start) + "ms");
    }

}


class FileUtil {
    private File srcFile;
    private File decFile;

    public FileUtil(String srcFile, String decFile) {
        this(new File(srcFile), new File(decFile));
    }

    public FileUtil(File srcFile, File decFile) {//初始化
        this.srcFile = srcFile;
        this.decFile = decFile;
    }

    public boolean copy() throws Exception {//拷贝操作
        if (!srcFile.exists()) {//判断源文件是否存在
            System.out.println("源文件不存在");
            return false;
        }

        if (!decFile.getParentFile().exists()) {//判断父目录是否存在
            decFile.getParentFile().mkdirs();//创建父目录
        }
        InputStream in = null;
        OutputStream out = null;
        try {
            in = new FileInputStream(this.srcFile);
            out = new FileOutputStream(this.decFile);
            in.transferTo(out);//转存
        } catch (Exception e) {
            throw e;
        } finally {//必须关闭
            if (in != null) {
                in.close();
            }
            if (out != null) {
                out.close();
            }
        }

        return true;
    }

}

结果:

文件拷贝成功
拷贝完成时间:9ms

<mark>此时千万要注意程序的运行版本问题。</mark>

文件夹拷贝功能

  那么如果说现在对此程序要求进一步扩展,可以实现一个文件目录的拷贝呢?一旦进行了文件目录的拷贝还需要拷贝所有的子目录中的文件。

文件夹拷贝代码:

public class JavaAPIDemo {
    public static void main(String[] args) throws Exception {
        if (args.length < 2) {
            System.out.println("请输入正确的参数");
            System.exit(1);//退出系统
        }
        long start = System.currentTimeMillis();
        FileUtil util = new FileUtil(args[0], args[1]);
        if (new File(args[0]).isDirectory()) {//是文件夹执行文件夹复制
            System.out.println(util.copyDir() ? "文件拷贝成功" : "文件拷贝失败");
        } else {
            System.out.println(util.copy() ? "文件拷贝成功" : "文件拷贝失败");
        }
        long end = System.currentTimeMillis();
        System.out.println("拷贝完成时间:" + (end - start) + "ms");
    }

}


class FileUtil {
    private File srcFile;
    private File decFile;

    public FileUtil(String srcFile, String decFile) {
        this(new File(srcFile), new File(decFile));
    }

    public FileUtil(File srcFile, File decFile) {//初始化
        this.srcFile = srcFile;
        this.decFile = decFile;
    }

    private void copyImpl(File file) throws Exception {
        if (file.isDirectory()) {
            File result[] = file.listFiles();//展开全部文件子目录
            if (result != null) {
                for (File t : result) {
                    copyImpl(t);//递归调用子目录
                }
            }
        } else {//如果是文件
            //将文件名改为新的文件名
            String srcFileName = file.getPath().replace(this.srcFile.getPath() + File.separator, "");
            File newFileName = new File(this.decFile, srcFileName);
            this.copyFileImpl(file, newFileName);//文件复制
        }
    }


    private boolean copyFileImpl(File srcFile, File decFile) throws Exception {//
        if (!decFile.getParentFile().exists()) {//判断父目录是否存在
            decFile.getParentFile().mkdirs();//创建父目录
        }
        InputStream in = null;
        OutputStream out = null;
        try {
            in = new FileInputStream(srcFile);
            out = new FileOutputStream(decFile);
            in.transferTo(out);//转存
        } catch (Exception e) {
            throw e;
        } finally {//必须关闭
            if (in != null) {
                in.close();
            }
            if (out != null) {
                out.close();
            }
        }
        return true;
    }

    public boolean copy() throws Exception {//拷贝操作
        if (!srcFile.exists()) {//判断源文件是否存在
            System.out.println("源文件不存在");
            return false;
        }
        return copyFileImpl(this.srcFile, this.decFile);
    }

    public boolean copyDir() {
        try {
            copyImpl(this.srcFile);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;

    }
}

结果:

文件拷贝成功
拷贝完成时间:604ms