使用Java的File类实现目录拷贝

准备工作

首先,我们来熟悉下File类!

在 Java 中,File 类是 java.io 包中唯一代表磁盘文件本身的对象,也就是说,如果希望在程序中操作文件和目录,则都可以通过 File 类来完成。File 类定义了一些方法来操作文件,如新建、删除、重命名文件和目录等。(这是xxxx上搜到的简介,我觉得很Good!)

这是俺的课堂笔记 (about how to understand File class)

1.File类和四大家族没有关系,所以File类不能完成文件的读和写 2.File对象代表什么? * 文件和目录路径名的抽象表象形式 * “Z:C++charAscii” 这是一个File对象 * “Z:C++QuicksortQuicksortDebug源.obj” 也是File对象 * 所以咱就是说,一个File对象有可能是对应的目录,也可能是文件,其本质就是,File只是一个路径名的抽象表示形式而已!!!

Case Analysis

将一个目录拷贝到另一个目录下

不过


虽然看这些干巴巴的文字确实很枯燥,但是写代码思路必须要清晰,要掌握整体思路是个啥样子,细节可以慢慢抠,“好的程序都是调试出来的!”(老师们也是这样认为滴^_^)

不过话说回来,个人认为倒也挺实在的(hhh……)

如果你本来对this case有了解过然后只想看看代码的话,就可以跳过这个枯燥的部分,或者你想先看看代码也可以,把代码的思路理清之后再回过头来看看总体思路也是没问题的(俺有时候就是这样干的,感觉没看到代码就……“先确认一下眼神!”^_^ ^_^)


  1.首先需要新建两个File类对象,因为对磁盘或者目录进行操作的话只能用File类来操作

  2.写一个Copy函数来完成这个拷贝操作,直接把原File对象copy到目标File对象中

  3.Copy函数
   我们要拷贝目录就需要把目录下的所有文件都拷贝过去,至于目录我们可以用mkdirs()函数来递归创建的多重目录,对于文件copy的话我们可以使用之前我们学过的字节输入输出流来对文件进行读写从而完成文件的复制。

1.首先我们需要知道文件的路径通过File类中的listFiles()函数可以获取目录或子文件,然后我们可以先将其放到一个File[]数组中后面再对其进行遍历在目标位置创建相应的目标目录

 2.上一步创建完目录之后,我们就可以对文件进行读写操作了,使用字节输入输出流来完成,根据上一步的经验,我们可以快速得出文件的绝对路径
注意:上面两步操作在代码执行过程中是同时进行的,便创建目录,边读写文件(目录是边递归边创建,文件也是在创建目录的同时进行读写的,读写的过程也是一边读一边写

代码实现

Well!下面俺们终于可以开始撸代码了!!!

package IO.com.proj;

import java.io.*;


public class CopyDirectory {
    public static void main(String[] args) {
        File srcFile = new File("Z:\C++");
        File destFile = new File("D:\a\c\");
        copyDir(srcFile,destFile);
    }

    /**
     *
     * @param srcFile  拷贝源
     * @param destFile 拷贝目标
     */
    private static  void copyDir(File srcFile, File destFile){
        //先对其进行判断是否是文件,如果是则可以进行拷贝操作,否则就对其继续递归
        /**
         * 通过前面的递归(执行顺序,其实递归入口放在了后面,用来递归创建目录)
         * 每次递归创建目录,当递归到文件了那么就进来这个if语句来对文件进行读写,读写完就return
         */
        if(srcFile.isFile()){
            //srcFile如果是一个文件的话,递归结束,此时需要对文件进行拷贝(从源文件中读出来再将其写道目标文件当中)
            //是文件的时候需要拷贝
            //……一边读一边写
            FileInputStream in = null;
            FileOutputStream out = null;

            try {
                in = new FileInputStream(srcFile);

                String path = (destFile.getAbsolutePath().endsWith("\")? destFile.getAbsolutePath(): destFile.getAbsolutePath()+"\") + srcFile.getAbsolutePath().substring(3);
                out = new FileOutputStream(path);

                //一边读一边写
                byte[] bytes = new byte[1024*1024];  //一次复制1MB
                int readCount;
                while((readCount = in.read(bytes))!=-1){
                    out.write(bytes,0,readCount);
                }
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }

            return;
        }


        //否则就继续获取目录下的子目录或者子文件
        File[] files = srcFile.listFiles();  //先获取目录或子文件并放到File[]数组中,后面再对其进行遍历并创建目录

        for(File file:files){
            System.out.println(file);
            //获取所有文件的(包括目录和文件)的绝对路径
            //System.out.println(file.getAbsolutePath());
            //Z:C++	est_Effective C++x64
            //Z:C++	est_Effective C++x64Debug
            if(file.isDirectory()){
               /* if(!file.exists()){
                    file.mkdirs();
                }*/
                /**
                 * 为什么不能直接向上面这样去创建目录呢?
                 * 如果直接这样创建了的话相当于没有执行if里面的语句,因为在这个目录本就存在所以根本不需要创建,
                 * (in this case)而我们要做的是把“Z:C++”里的东西拷贝到”D:ac\“当中,所以必须把路径先改变了(在新路径下新建)
                 */
               String srcDir = file.getAbsolutePath();
               //改变路径   把”Z:C++“改成”D:acC++“,准确来说是把”Z:“改成”D:ac“
                //Z:C++charAscii
                //D:acC++charAscii
               //因为"D:\a\c\" 不确定是否以”“结尾,所以需要判断一下,否则直接可以将srcDir赋给destDir
               String destDir = (destFile.getAbsolutePath().endsWith("\")? destFile.getAbsolutePath(): destFile.getAbsolutePath()+"\")+srcDir.substring(3);
                //System.out.println(destDir);
                //改完路径之后我们再新建一个File对象,用新路径来初始化这个对象
                File newFile = new File(destDir);
                if (!newFile.exists()){
                    newFile.mkdirs();    //会自动对次对象进行回收处理的
                }
                //到此为止,我们便在目标位置下把目标目录顺利新建成功
            }
            //递归调用(目录是一层一层的,就像一棵树,要递归一个一个去建
            copyDir(file,destFile);
        }
    }
}

                       


总结

目录拷贝这个case对于初学者来说可能有点小难度,因为中间涉及到了递归,递归比较抽象,不过没关系,当你的代码量达到了一定的量,写着写着自然就熟悉了。这个case涉及到了File类的使用,把字节输入输出流也应用到其中来了,“学以致用”,顺便巩固前面的知识点,所以俺们当练练手好了!但是对于一个demo刚开始写 by yourself ,可能不太好上手,但是思路一定要清晰!!!
经验分享 程序员 微信小程序 职场和发展