文章目录
- 题目描述:扫描指定目录,并找到文件名称或文件内容中包含指定字符的所有普通文件(不包含目录)
- 结果案例演示:
- 设计思路:
- 总体的思路:
- 使用代码,分步实现
- 1. 准备工作(输入目录路径,创建File对象,判断,输入关键字)
- 2. 开始遍历目录
- 3. 实现scanDir方法
- 3.1 获取到目录中的所有文件(File对象),同时,判断该目录是否为一个空目录
- 3.2 遍历当前目录中的内容,然后判断当前文件时普通文件还是目录,两种情况:
- 3.2.1 如果是普通文件,则调用dealFile方法,进行文件名或文件内容的判定
- 3.2.2 如果是目录,则递归调用本方法
- 4. 实现dealFile方法
- 4.1 判定文件名是否包含关键字
- 4.2 判定文件内容是否包含关键字
- 4.2.1 设置 StringBuilder,把读到的字符内容拼接到 stringBuilder
- 4.2.2 由于 关键字 是字符串,读取文件内容使用 字符流 的方式来进行处理
- 4.2.3 循环读取,且一次读取多个字节,所以需要创建一个字符数组
- 4.2.4 使用append( ),进行追加操作,读到多少,追加多少
- 4.2.5 拼接读取完毕后,stringBuilder 就是文件内容中的字符,判断 stringBuilder 是否包含关键字,有两种判断方式:
- 完整代码:
- 总结:
题目描述:扫描指定目录,并找到文件名称或文件内容中包含指定字符的所有普通文件(不包含目录)
本题还是进行目录的搜索,和 扫描指定目录,并找到名称中包含自定字符的所有普通文件(不包含目录),并且后续询问用户是否要删除该文件,这篇博客介绍的程序差不多,但是本次不是删除,而是要加上一个文件内容读取的步骤。
本次的程序,不仅要找到文件名称中包含指定字符的普通文件,还要找到文件内容中包含指定字符的普通文件。
例如:关键词为 test,那么这个程序可以找到文件名中有 test 这个字符的文件,也可以找到文件内容有 test 这个字符的文件。
结果案例演示:
以下的演示,我统一以我本人当前该程序的项目路径为例:
E:\code\gitee\JAVA代码\java-code-\java_File_IO_11.28
关键词,以 test 为例子。
运行结果:
设计思路:
总体的思路:
准备工作:
第一步:我们需要让用户输入一个指定的目录,确定搜索的是哪个目录,搜索该目录里面的文件。
第二步:根据用户输入的目录路径,创建 File对象,同时,判定用户输入的目录路径,是否为一个目录,如果不是,则不进行搜索,直接 return 结束程序。
第三步:如果用户输入的目录路径是一个目录,就让用户输入要文件名或文件内容包含的关键字。
以上步骤没有问题以后,我们就开始遍历目录了。
遍历目录:
遍历目录的代码,我们写到一个方法里面,scanDir方法,传入两个变量:
- 第一个变量:根据目录的路径所创建的 File对象(我代码中的 rootfile),
- 第二个变量:要删除的文件中,文件名包含的关键字(我代码中的 keyword)。
scanDir方法 遍历目录内容的步骤:
- 获取目录中的所有文件(File对象),使用 File数组 进行接收,同时,判断这个数组的引用是否为空(null),进而判断该目录是否为一个空目录(即目录什么文件都没有,
listFiles()
就会返回 null)。
如果是空的,直接返回,不用进行遍历了。 - 目录内容不为空后,遍历当前目录中的内容(File数组),然后判断当前文件是 普通文件 还是 目录,两种情况:
2.1 如果是 普通文件,则 调用dealFile方法,进行判定是否存在关键字
2.2 如果是 目录,则递归调用本方法(scanDir方法)
dealFile方法 对文件名和文件内容进行判定,是否包含关键字(keyword):
- 判定文件名是否包含关键字,如果文件名包含关键字,就打印出该文件的绝对路径,并且 return,结束该方法,如果文件名不包含关键字,则判定文件内容是否包含关键字
- 判定文件内容是否包含关键字:
先读取到文件中的内容,用 StringBuilder 类,拼接成一个字符串,再去用关键字和这个字符串进行判断
2.1 由于 关键字 是字符串,所以我们这里就用字符流的方式来进行处理
2.2 此处是采用一次性读取多个字符,所以需要创建一个 字符数组(char[ ]),接收读取到的字符,大小任意
2.3 实例化 StringBuilder类 的对象 stringBuilder,把读到的字符内容拼接到 stringBuilder,进行追加写操作,且读到多少,追加多少,stringBuilder.append(chars,0,n);
,0 表示从char[ ]数组的起始下标开始追加,n 表示此次读取到的字符数。
2.4 判断 stringBuilder是否包含关键字,列举两种判断方式:
- 第一种:使用
if (stringBuilder.indexOf(keyword) >= 0)
,判断思路:从 stringBuilder 的0下标开始找,找到 keyword表示的关键字 后,返回其 字符串的首字符下标。只要找到,返回的字符串的首字符下标,**必然是 大于等于0(>=0)**的数字,如果没找到,返回 -1。 - 第二种:使用
stringBuilder.toString().contains(keyword)
,判断思路:使用 toString( )方法,输出为字符串后,再用 contains( )方法,判断是否包含关键字。
关于 indexOf( )方法,不熟悉的,可以查看 Java的String类(上),这篇博客中 2.4.2 标题的内容,里面清楚的介绍了 indexOf( )方法。
这道题目,相比于示例一那道题目,区别在于,需要读取文件中的内容,并且拼接到字符串中,再去判断,字符串中是否包含关键字。
使用代码,分步实现
1. 准备工作(输入目录路径,创建File对象,判断,输入关键字)
// 准备工作:
// 第一步:输入指定的目录路径Scanner scanner = new Scanner(System.in);System.out.println("输入你要搜索的目录的路径(绝对 or 相对):");String rootDir = scanner.next();// 第二步:根据输入的目录路径,创建File文件File rootfile = new File(rootDir);
// 其次,判断这个文件是否为一个目录,不是目录,则退出程序if (!rootfile.isDirectory()){System.out.println("你输入的路径不是一个目录!");return;}// 第三步:输入关键字System.out.println("请输入目录中的文件的文件名所包含的关键字:");String keyword = scanner.next();
2. 开始遍历目录
scanDir(rootfile,keyword);
3. 实现scanDir方法
private static void scanDir(File rootfile, String keyword) {}
3.1 获取到目录中的所有文件(File对象),同时,判断该目录是否为一个空目录
// 第一步:使用listFiles()获取到目录中的各个文件File[] files = rootfile.listFiles();
// 判断目录是否为空目录if (files == null) {return;}
3.2 遍历当前目录中的内容,然后判断当前文件时普通文件还是目录,两种情况:
// 第二步:对每个文件进行判定,判断是不是目录for (File file:files) {if (file.isFile()) {
// 如果这个文件是一个普通文件,进行文件名和文件内容的判定dealFile(file, keyword);} else {
// 如果不是文件,就应该是目录,使用递归的方式,深度搜索scanDir(file,keyword);}}
3.2.1 如果是普通文件,则调用dealFile方法,进行文件名或文件内容的判定
//1.如果这个文件是一个普通文件,调用dealFile方法,进行文件名和文件内容的判定
dealFile(file, keyword);
3.2.2 如果是目录,则递归调用本方法
//2.如果是目录,则递归调用本方法
scanDir(file,keyword);
4. 实现dealFile方法
private static void dealFile(File file, String keyword) {}
4.1 判定文件名是否包含关键字
// 1.判定文件名是否包含关键字if (file.getName().contains(keyword)) {System.out.println("文件名包含关键字:" + file.getAbsolutePath());return;}
4.2 判定文件内容是否包含关键字
// 2.判定文件内容是否包含关键字
// 设置 StringBuilder,把读到的字符内容拼接到 stringBuilderStringBuilder stringBuilder = new StringBuilder();
// 读取文件内容的操作
// 由于keyword是字符串,就按照字符流的方式来进行处理try(Reader reader = new FileReader(file)) {while (true) {char[] chars = new char[1024];int n = reader.read(chars);
// 判断是否读取完毕if (n == -1) {break;}
// 把读到的每一段内容,都进行一个追加操作
// 读到多少,追加多少stringBuilder.append(chars,0,n);}// 判断 StringBuilder 是否包含关键字// 第一种判断方式:
// if (stringBuilder.toString().contains(keyword)) {
包含关键字
// System.out.println("文件内容包含关键字:" + file.getAbsolutePath());
// }// 第二种判断方式:if (stringBuilder.indexOf(keyword) >= 0) {
// 包含关键字System.out.println("文件内容包含关键字:" + file.getAbsolutePath());}} catch (IOException e) {throw new RuntimeException(e);}
4.2.1 设置 StringBuilder,把读到的字符内容拼接到 stringBuilder
// 设置 StringBuilder,把读到的字符内容拼接到 stringBuilderStringBuilder stringBuilder = new StringBuilder();
4.2.2 由于 关键字 是字符串,读取文件内容使用 字符流 的方式来进行处理
// 由于keyword是字符串,就按照字符流的方式来进行处理try(Reader reader = new FileReader(file)) {
// 读取文件的操作....} catch (IOException e) {throw new RuntimeException(e);}
4.2.3 循环读取,且一次读取多个字节,所以需要创建一个字符数组
while (true) {char[] chars = new char[1024];int n = reader.read(chars);
// 判断是否读取完毕if (n == -1) {break;}}
4.2.4 使用append( ),进行追加操作,读到多少,追加多少
// 把读到的每一段内容,都进行一个追加操作
// 读到多少,追加多少stringBuilder.append(chars,0,n);
4.2.5 拼接读取完毕后,stringBuilder 就是文件内容中的字符,判断 stringBuilder 是否包含关键字,有两种判断方式:
- 第一种:使用
if (stringBuilder.indexOf(keyword) >= 0)
,判断思路:从stringBuilder 的0下标开始找,找到 keyword表示的关键字 后,返回其 字符串的首字符下标。只要找到,返回的字符串的首字符下标,必然是 大于等于0(>=0)的数字,如果没找到,返回 -1。
// 第一种判断方式:if (stringBuilder.toString().contains(keyword)) {
// 包含关键字System.out.println("文件内容包含关键字:" + file.getAbsolutePath());}
- 第二种:使用
stringBuilder.toString().contains(keyword)
,判断思路:使用 toString( )方法,输出为字符串后,再用 contains( )方法,判断是否包含关键字。
// 第二种判断方式:if (stringBuilder.indexOf(keyword) >= 0) {
// 包含关键字System.out.println("文件内容包含关键字:" + file.getAbsolutePath());}
完整代码:
import java.io.*;
import java.util.Scanner;public class demo4 {public static void main(String[] args) {
// 准备工作:
// 第一步:输入指定的目录路径Scanner scanner = new Scanner(System.in);System.out.println("输入你要搜索的目录的路径(绝对 or 相对):");String rootDir = scanner.next();// 第二步:根据输入的目录路径,创建File文件File rootfile = new File(rootDir);
// 其次,判断这个文件是否为一个目录,不是目录,则退出程序if (!rootfile.isDirectory()){System.out.println("你输入的路径不是一个目录!");return;}// 第三步:输入关键字System.out.println("请输入目录中的文件的文件名所包含的关键字:");String keyword = scanner.next();scanDir(rootfile,keyword);}private static void scanDir(File rootfile, String keyword) {
// 第一步:使用listFiles()获取到目录中的各个文件File[] files = rootfile.listFiles();// 第二步:对每个文件进行判定,判断是不是空目录for (File file:files) {if (file.isFile()){
// 如果这个文件是一个普通文件,就进行删除判定dealFile(file, keyword);} else {
// 如果不是文件,就应该是目录,使用递归的方式,深度搜索scanDir(file,keyword);}}}private static void dealFile(File file, String keyword) {
// 1.判定文件名是否包含关键字if (file.getName().contains(keyword)) {System.out.println("文件名包含关键字:" + file.getAbsolutePath());return;}
// 2.判定文件内容是否包含关键字
// 设置 StringBuilder,把读到的字符内容拼接到StringBuilderStringBuilder stringBuilder = new StringBuilder();
// 读取文件内容的操作
// 由于keyword是字符串,就按照字符流的方式来进行处理try(Reader reader = new FileReader(file)) {while (true) {char[] chars = new char[1024];int n = reader.read(chars);
// 判断是否读取完毕if (n == -1) {break;}
// 把读到的每一段内容,都进行一个追加操作
// 读到多少,追加多少stringBuilder.append(chars,0,n);}// 判断 StringBuilder 是否包含关键字// 第一种判断方式:
// if (stringBuilder.toString().contains(keyword)) {
包含关键字
// System.out.println("文件内容包含关键字:" + file.getAbsolutePath());
// }// 第二种判断方式:if (stringBuilder.indexOf(keyword) >= 0) {
// 包含关键字System.out.println("文件内容包含关键字:" + file.getAbsolutePath());}} catch (IOException e) {throw new RuntimeException(e);}return;}
}
总结:
这一个代码,对于搜索文件,总体来说,是一个比较低效的方法。
因为我们这个查找过程,我们需要针对所有的文件的文件名和文件内容进行遍历,整体的一个遍历的开销,如果文件多的话,这种开销是比较大的。
如果,你搜的是整个 C盘(算是一个很大的目录),那么,搜索的时间就很久了,你可以自己试试。
总体来说,是一个比较慢的方案。
更高效的方案,就是“搜索引擎”。例如:百度,搜狗等。
搜索引擎做的事情,就是在海量的文件当中,找到哪些文件的内容包含了关键字,而且,还要识别出哪些文件的相关性更高,排到前面。
搜索引擎,会有一系列的优化,提高搜索的效率,最核心的技术点,叫做:“倒排索引”。
至于 “倒排索引”,是什么,原理是什么,这里就不展开说了,有兴趣的,可以去 B站,搜索视频看一下。
最后,如果这篇博客有帮到你的,请你点点赞,有写错了,写的不好的,欢迎评论指出,谢谢!