关于文件操作,笔者在前面文章中讲解了关于:文件操作和IO的文章,感兴趣的各位老铁可以看一下:文件操作和IO-CSDN博客
那么,我们来看一下今日的一个主题:
- 文件系统操作File类:——》文件资源管理器能干啥??这里咱们就能干啥??
- 文件内容操作:流对象
流对象:
字节流:InputStream OutputStream
字符流:Reader Writer
基本步骤:
- 创建对象(打开文件):指定文件路径绝对路径:从盘符开始
相对路径:以“ . ”或者“ ..”开头的,必须要有一个基准目录/工作目录 - 读写文件:read write
read:一个文件读完了,就会返回-1,作为结束标志(while循环)
read()的无参数版本,返回该字节的内容
read(byte[] buffer , int offset , int length)读到buffer数组中,但不是从头放,是从offset位置放,最多放length这么长,返回值也是实际读的长度!!
read(byte[] buffer)将读到的内容放到buffer数组中,返回值是读到的字节数
- 关闭文件:close!
文件操作案列:
扫描指定目录,并指到名称或者内容中包含指定字符的所有普通文件(不包含目录),遍历目录,在里面的文件中查找!(这个功能类似于全文检索功能),如:你在电脑上有很多目录,目录上有很多文件,假设某些文件中包含“hello world”关键字!!这个程序就是找出哪些文件是包含这个关键词的!!
那么,我们来简单粗暴的实现一下吧:
- 先去递归的遍历目录,如:给定一个d:/(d盘),去递归的把这里包含的文件都列出来
- 每次找到一个文件,都打开,并读取文件内容(得到String)
- 在判定要查询的词,是否在上述文件内容存在,如果存在,结果即为所求!!
上述的这种方式并不高效,小规模的搜索还是可以的!更高效的实现就要依赖“倒排索引”这样的数据结构了(高阶)!
那么,按照上述思路,我们有着下述代码:
import java.io.File; import java.io.FileReader; import java.io.IOException; import java.io.Reader; import java.util.Scanner; public class Main { //简单粗暴的实现一下:文件操作! public static void main(String[] args) { Scanner scanner=new Scanner(System.in); //1.先让用户指定一个要搜索的根目录 System.out.println("请输入要扫描的根目录:"); //rootDir根目录 File rootDir=new File(scanner.next()); if (!rootDir.isDirectory()){ System.out.println("输入有误,你输入的目录不存在"); return;//目录不存在,直接返回 } //2。让用户输入一个要查询的词 System.out.println("请输入要查询的词"); //word要查找的词 String word=scanner.next(); //3.递归的进行目录/文件的遍历了 //递归是为了避免:目录里可能还包含其他目录 scanDir(rootDir,word); //目录结构是“N叉树”,树本身就是递归定义的,通过递归的方式来进行处理,其实还是比较合适的! } private static void scanDir(File rootDir,String word){ //列出当前的rootDir中的内容,没有内容直接递归结束 File[] files=rootDir.listFiles(); //rootDir.listFiles()列出目录中的内容 if (files==null){ //当前rootDir是一个空的目录,这里啥都没有 //没必要往里递归了 return;//目录里啥都没有 } //目录里有内容,就遍历目录中的每个元素 for (File f:files) { System.out.println("当前搜索到:" + f.getAbsolutePath()); if (f.isFile()){ //是普通文件 //打开文件,读取内容,比较看是否包含上述关键词 String content=readFile(f); if (content.contains(word)){ //如果包含,则打印………… System.out.println(f.getAbsolutePath()+"包含要查找的关键字"); } }else if (f.isDirectory()){ //是目录 //进行递归操作 scanDir(f,word); //此处的递归,其实就是以当前f这个目录作为起点,在搜索里面的内容了!! }else { //不是普通文件,也不是目录文件,直接跳过(以Linux为列,就有七种文件类型!) continue; } } } private static String readFile(File f){ //读取文件的整个内容,返回出来 //使用字符流来读取,由于咱们匹配的是字符串,此处只能按照字符流来处理,才有意义 StringBuilder stringBuilder=new StringBuilder(); try(Reader reader=new FileReader(f)) { //一次读一个字符,把读到的结果给拼装到StringBuilder中 //统一转成String while (true){ //一次读一个字符 int c=reader.read(); if (c==-1){ break; } stringBuilder.append((char) c); //c 本身是int类型,我们需要强转为char类型,确保c不能超过char的数据范围!! } }catch (IOException e){ e.printStackTrace(); } return stringBuilder.toString(); } }
上述的代码没有考虑到文件特别大(栈溢出),内存存不下的情况!!!
如果确实需要考虑这种情况,那么,我们将文件分块读取即可!!
对于二进制文件:难点不是读,可以很容易把每个字节都读出来!但是不同的二进制文件,里面字节的含义是不同的,不能理解这里是啥意思!!
比如:word,写个“hello word”,这个时候,可以整个word文件里都没有“hello word”,这个字符串,可能是通过其他方式转成二进制保存,这就需要你理解word的二进制格式,才能做解析,才能查找!!