需求:将H盘下的所有文件复制到H:/All 文件夹中
思路:使用递归遍历整个目标目录

  1. 传入目标路径
  2. 判断是否是文件夹
    是:调用listFiles()方法,得到File数组,重点内容接着执行1
    否:复制文件到H:/All

源码:

package FunDemo;

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;

public class Demo2 {
    static FileWriter fw = null;

    public static void main(String[] args) throws Exception {
        File file = new File("H:/");
        sb(file);
    }

    private static void sb(File file) throws Exception {
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            if (files != null) {
                for (File f : files) {
                    sb(f);
                }
            }
        }
        if (file.isFile()) {
            FileReader fr = new FileReader(file.getAbsolutePath());
            char[] cha = new char[1024];
            fw = new FileWriter("H:/All/" + file.getName());
            while (fr.read(cha) != -1) {
                fw.write(cha, 0, cha.length);
                fw.flush();
            }
            fw.close();
        }
    }
}

在解决这个问题 的过程中,遇到一个问题,其中一部分原代码片是这样的

if (file.isDirectory()) {
            File[] files = file.listFiles();
                for (File f : files) {
                    sb(f);
            }
        }

在执行的过程中,出现了空指针异常。为此,我有些疑惑,哪里来的空指针?
文件调用listFiles会返回null吗?文件夹呢?带着这个问题,首先我们来实验一下,数组出现空指针的情况;
情况一:

int []in = {};
        for(int i:in) {
            System.out.println(i);
        }

控制台没有输出,但是并不会出现空指针异常。
情况二:

int []in = null;
        for(int i:in) {
            System.out.println(i);
        }

此时,控制台会抛出空指针异常。java.lang.NullPointerException


所以,程序出现空指针异常的原因清楚了,因为存在file调用listFiles返回的数组是null。
又要问,为什么存在file调用listFiles返回的数组是null?
首先,我们来分析文件和文件夹调用listFiles是否都会有返回null的可能?
情况一:file为文件时

File file = new File("H:/test.txt");
        File[] files = file.listFiles();
        if (files == null) {
            System.out.println("files为Null");//files为Null
        }

此时,调用listFiles()返回null。
情况二:file为一个空的文件夹时

File fil=new File("H:/test");
        File[] fils = fil.listFiles();
        if (fils == null) {
            System.out.println("fils为Null");//没有输出
        }

此时,调用listFiles()没有输出,这很好理解,因为文件夹内为空,不会有输出。
然而,这就很奇怪了,因为在上述代码中,执行listFiles()前存在if (file.isDirectory()) 的前提,怎么会出现null的情况呢?
在这种情况下,我们查看javase api查看listFiles()的说明,发现存在这样一句话,如果抽象路径名不表示一个目录,或者发生 I/O 错误,则返回 null。唯一的解释就是发生了I/O错误,这是怎么回事呢?通过上网查阅资料,发现,存在一些文件/文件夹的访问权限很高,我们没有权限对其进行读写,此时就发生了所谓的I/O错误。
那么,知道了原因,就好办了,那么,这样可以解决吗?

if (file.isDirectory()) {
            File[] files = null;
            if (file.canRead()) {
                file.listFiles();
                for (File f : files) {
                    sb(f);
                }
            }
        }

其实,这样也是不可以的,因为当不可读是files仍然是null,没有改变问题,所以解决方法就变成了最终样式:

if (file.isDirectory()) {
            File[] files = file.listFiles();
            if (files != null) {
                for (File f : files) {
                    sb(f);
                }
            }
        }

欢迎留言,欢迎指正~