文件内容操作练习
练习1
扫描指定目录,并找到名称中包含指定字符的所有普通文件(不包含目录),并且后续询问用户是否要删除该文件.
package javaEE.fileIO;
import java.io.File;
import java.util.Scanner;
public class O {
private static void scan(File currentFile, String key) {
if (!currentFile.isDirectory()) {
return;
}
File[] files = currentFile.listFiles();
if (files == null || files.length == 0) {
return;
}
for (File f : files) {
if(f.isFile()) {
// 针对普通文件进行处理,判定文件名是否符合要求并提示用户删除
doDelete(f,key);
} else {
scan(f,key);
}
}
}
private static void doDelete(File f,String key) {
if(!f.getName().contains(key)) {
//文件名中不包含指定的关键字
return;
} else {
// 提示用户是否要删除
Scanner scanner = new Scanner(System.in);
System.out.println(f.getAbsolutePath() + "确认删除?Y/N");
String choice = scanner.next();
if(choice.equals("Y") || choice.equals("y")) {
f.delete();
}
}
}
public static void main(String[] args) {
System.out.println("请输入要搜索的路径");
Scanner scanner = new Scanner(System.in);
String rootPath = scanner.next();
File rootFile = new File(rootPath);
if (!rootFile.isDirectory()) {
System.out.println("输入的路径不存在");
return;
}
System.out.println("请输入要删除的文件名字的关键字");
String key = scanner.next();
// 进行递归查找
scan(rootFile, key);
}
}
代码运行前:
代码运行后:
练习2
进行普通文件的复制.
package javaEE.fileIO;
import java.io.*;
import java.util.Scanner;
public class P {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入原文件的路径:");
String srcPath = scanner.next();
File srcFile = new File(srcPath);
// 原文件需要确保路径存在,并且还要是一个文件
if(!srcFile.isFile()) {
System.out.println("原文件路径有误!");
return;
}
System.out.println("请输入目标文件的路径");
String destPath = scanner.next();
File destFile = new File(destPath);
// 目标文件需要确保目录存在
if(!destFile.getParentFile().isDirectory()) {
System.out.println("目标文件的路径有误");
return;
}
// try()里可以写多个对象,多个对象的构造过程使用 ; 分隔
try(InputStream inputStream = new FileInputStream(srcFile);
OutputStream outputStream = new FileOutputStream(destFile)) {
while (true) {
byte[] buffer = new byte[1024];
int n = inputStream.read(buffer);
if(n == -1) {
break;
}
// 这里一定要指定区间,因为在最后一次从文件中读数据时,不一定是1024个字节!!
outputStream.write(buffer,0,n);
}
}catch (IOException e) {
e.printStackTrace();
}
}
}
运行前:
运行后:
练习3
扫描指定路径,并找到名称或者内容中包含指定字符的所有普通文件(不包含目录)
package javaEE.fileIO;
import java.io.*;
import java.nio.file.Files;
import java.util.Scanner;
public class Q {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入要搜索的目录");
String rootPath = scanner.next();
File rootFile = new File(rootPath);
if (!rootFile.isDirectory()) {
System.out.println("要搜索的路径有误!");
return;
}
System.out.println("请输入要搜索的查询词:");
String key = scanner.next();
// 进行查询
scan(rootFile, key);
}
private static void scan(File rootFile,String key) {
if(!rootFile.isDirectory()) {
return;
}
File[] files = rootFile.listFiles();
if(files == null || files.length == 0) {
return;
}
for (File f: files) {
if(f.isFile()) {
// 进行查询
doSearch(f,key);
} else {
// 进行递归
scan(f,key);
}
}
}
private static void doSearch(File f,String key) {
StringBuilder stringBuilder = new StringBuilder();
// 打开文件,读取文件内容,判定文件内容是否包含key
try(Reader reader = new FileReader(f)) {
char[] buffer = new char[1024];
while (true) {
int n = reader.read(buffer);
if(n == -1) {
break;
}
String s = new String(buffer,0,n);
stringBuilder.append(s);
}
} catch (IOException e) {
e.printStackTrace();
}
if(stringBuilder.indexOf(key) == -1) {
// 没找到
return;
}
// 找到了
System.out.println("找到匹配的文件" + f.getAbsolutePath());
}
}
运行结果
此处这里的代码逻辑,效率是非常低的,每次查询,都会涉及到大量的硬盘IO操作.
这种思路,不能适应频繁查询的场景,也不能适应目录中文件数目特别多,特别大的场景.
这种基于内容的查询,其实也是存在的,比如说搜索引擎.
搜索引擎在进行搜索的过程,也就是在文件中查找内容是否被包含的过程.
搜索出来的结果其实就是一些html文件.
这些html文件里面一定是包含你的查询词(或者和你的查询词有关联)
这是在数以十亿,数以百亿的html中,找到了30w个结果.
搜索引擎这样的场景,不能通过上述"遍历文件"的方式实现.
其中最核心的优化,就是引入了神奇的数据结构"倒排索引".提前把所有的文件里面的内容都分析好,分析出一个文件中,包含哪些词~
然后基于这个结果,得到另一份数据,每个词,都在哪些文件中包含着~
实际工作中,也会用到一些"自定制的搜索引擎".
比如,我们自己的代码中,产生大量的日志,把这些日志,导入到自己搭建的搜索引擎中(用到一些业界成熟的方案,比如ES这种),从而快速查找~
关于文件操作就讲到这里了~
本文到这里就结束啦~