前言
在开发或者面试的过程中,往往会遇到这样的需求,就是读取某个目录下的所有文件(内容),并且文件夹的层级不固定。基于这样的情况,博主写了个对应的demo,以备不时之需。
分析
文件系统层级关系可以看成是树形结构,读取某个目录下的所有文件,其实就是遍历一颗树,树的遍历分为深度优先和广度优先。对应的,分别写了两个小demo。
深度优先
深度优先搜索算法(Depth-First-Search,DFS)是一种用于遍历或搜索树或图的算法。沿着树的深度遍历树的节点,尽可能深的搜索树的分支。
/**
* 调用:readFileTree("D:\\directory");
* @param rootPath
* @throws IOException
*/
public void readFileTree(String rootPath) throws IOException {
File rootFile = new File(rootPath);
if (!rootFile.exists()) {
System.out.println("路径错误");
return;
}
System.out.println(rootPath);
FileInputStream is = null;
BufferedReader reader = null;
StringBuilder sb = new StringBuilder();
if (rootFile.isFile()) {
//如果当前路径是文件,读取内容
is = new FileInputStream(rootFile);
reader = new BufferedReader(new InputStreamReader(is, "GBK"));
String content = null;
while ((content = reader.readLine()) != null) {
sb.append(content);
}
System.out.println("文件内容 : " + sb.toString());
} else {
//如果当前路径是文件夹,则列出文件夹下的所有文件和目录
File[] files = rootFile.listFiles();
for (File file : files) {
//递归调用
readFileTree(file.getAbsolutePath());
}
}
if (reader != null) {
reader.close();
}
if (is != null) {
is.close();
}
}
输出结果:
D:\directory
D:\directory\pkg1
D:\directory\pkg1\pkg1-1
D:\directory\pkg1\pkg1-2
D:\directory\pkg1\pkg1-2\pkg1-2-test.txt
文件内容 : 对酒当歌,人生几何。
D:\directory\pkg1\pkg1-3
D:\directory\pkg2
D:\directory\pkg2\pkg2-1
D:\directory\pkg2\pkg2-2
D:\directory\pkg3
D:\directory\pkg3\pkg3-test.txt
文件内容 : 何以解忧,唯有杜康。
D:\directory\pkg4
D:\directory\pkg4\pkg4-1
D:\directory\pkg4\pkg4-1\pkg-4-1-test.txt
文件内容 : 月明星稀,乌鹊南飞。
从输出结果可以看出是深度优先。
广度优先
广度优先搜索算法(Breadth-First-Search,缩写为BFS),又译作宽度优先搜索,或横向优先搜索,是一种图形搜索算法。简单的说,BFS是从根节点开始,沿着树的宽度遍历树的节点。如果所有节点均被访问,则算法中止。
private static Queue<String> pathQueue = new LinkedList<>();
public synchronized void readFileTree(String rootPath) throws IOException {
File rootFile = new File(rootPath);
if (!rootFile.exists()) {
System.out.println("路径错误");
return;
}
System.out.println(rootPath);
FileInputStream is = null;
BufferedReader reader = null;
StringBuilder sb = new StringBuilder();
if (rootFile.isFile()) {
//如果当前路径是文件,读取内容
is = new FileInputStream(rootFile);
reader = new BufferedReader(new InputStreamReader(is, "GBK"));
String content = null;
while ((content = reader.readLine()) != null) {
sb.append(content);
}
System.out.println("文件内容 : " + sb.toString());
} else {
//如果当前路径是目录,则把文件夹下的所有文件和目录路径加入队列
File[] files = rootFile.listFiles();
for (File file : files) {
pathQueue.add(file.getAbsolutePath());
}
}
//队列非空时,取出path读取
while (!pathQueue.isEmpty()) {
readFileTree2(pathQueue.remove());
}
if (reader != null) {
reader.close();
}
if (is != null) {
is.close();
}
}
输出结果:
D:\directory
D:\directory\pkg1
D:\directory\pkg2
D:\directory\pkg3
D:\directory\pkg4
D:\directory\pkg1\pkg1-1
D:\directory\pkg1\pkg1-2
D:\directory\pkg1\pkg1-3
D:\directory\pkg2\pkg2-1
D:\directory\pkg2\pkg2-2
D:\directory\pkg3\pkg3-test.txt
文件内容 : 何以解忧,唯有杜康。
D:\directory\pkg4\pkg4-1
D:\directory\pkg1\pkg1-2\pkg1-2-test.txt
文件内容 : 对酒当歌,人生几何。
D:\directory\pkg4\pkg4-1\pkg-4-1-test.txt
文件内容 : 月明星稀,乌鹊南飞。
从输出结果可以看出,搜索是按照层次来遍历的,即广度优先。
总结
博主算法渣,如果各位同学有更优雅的实现方式,还请不吝赐教。