【文件IO】实现:查找文件并删除、文件复制、递归遍历目录查找文件

简介: 【文件IO】实现:查找文件并删除、文件复制、递归遍历目录查找文件

一、文件查找并删除

扫描指定⽬录,并找到名称中包含指定字符的所有普通⽂件(不包含⽬录),并且后续询问⽤⼾是否 要删除该⽂件

一个主要的操作就是需要扫描指定目录(递归)

递归函数

  1. 首先判断是否是目录,若不是,直接返回
  2. 若是,则列出当前目录的文件名,放到 files 数组中
  3. 如果 files 是空的,或者 files 数组长度为 0,代表没有文件,则直接返回
  4. 循环遍历 files数组
  1. 若此时遍历到的文件是普通文件
  • 调用删除文件方法 doDelete
  1. 若磁石遍历到的仍是目录
  • 继续递归
public class Demo15 {  
    //递归目录的方法  
    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);  
            }        
        }    
    }
}

删除函数

  1. 文件名中不包含关键字,则直接返回
  2. 若包含,则提示用户,是否进行删除
  3. 用户输入 Y/N 进行选择
  4. 若输入为 Y y,则将此文件删除
private static void doDelete(File f, String key){  
    if(!f.getName().contains(key)){  
        return;  
    }    
    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();  
    }
}

完整代码

import java.io.File;  
import java.util.Scanner;  
  
public class Demo15 {  
    //递归目录的方法  
    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;  
        }        
        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);  
    }
}

二、文件复制

进⾏普通⽂件的复制

把一个文件里面的每个字节都读出来,再写入另一个文件中

  1. 输入源文件路径,并实例出一个 srcFile 对象
  2. 判断这个对象是否是一个文件,若不是,则返回
  3. 若是,则继续输入目标文件的路径
  4. 以这个路径实例化出一个 dextFile 文件
  5. 得到这个文件所在处的父目录,并判断其是否是一个目录
  6. 若是,则开始执行复制的过程
  • 通过 InputStream 进行读操作,OutputStream 进行写操作
import java.io.*;  
import java.util.Scanner;  
  
public class Demo16 {  
    public static void main(String[] args) throws IOException {  
        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(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;  
                }                
                outputStream.write(buffer,0,n);  
            }        
        }catch (IOException e){  
            e.printStackTrace();  
        }    
    }
}
  • try() 里面可以写多个对象,多个对象的构造过程使用 ; 分隔就可以了
  • 写入的时候,不能直接write(buffer),因为前面读操作不一定能把buffer填满,若直接写入buffer,就把没有用到的空间也写入了,不太合适
  • 也许 buffer 只填了 100 个空间,剩下 924 个空间都是 0,写入就没有意义
  • 此时我们就需要指定空间写入[0, n]

三、递归遍历目录查找文件

扫描指定⽬录,并找到名称或者内容中包含指定字符的所有普通⽂件(不包含⽬录) 注意:我们现在的⽅案性能较差,所以尽量不要在太复杂的⽬录下或者⼤⽂件下实验

import java.io.*;  
import java.util.Scanner;  
  
  
  
public class Demo17 {  
    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.length == 0 || files == null) {  
            return;  
        }        
        for(File f : files) {  
            if(f.isFile()){  
                //进行后续的查询操作  
                doSearch(f,key);  
            }else{  
                scan(f,key);  
            }        
        }    
    }  
  
    private static void doSearch(File f, String key) {  
        //打开文件,读取文件内容,并判定文件内容是否包含 key        
        StringBuilder stringBuilder = new StringBuilder();  
        //因为不考虑二进制,直接按照文本的方式来处理,就直接用 Reader        
        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 中,找到几十万,几百万个结果

搜索引擎这样的场景,不能通过上述“遍历文件”方式实现

  • 其中最核心的优化,是引入了神奇的数据结构——倒排索引
  • 提前把所有的文件,里面的内容都分析好,分析出一个文件中,包含哪些词,再基于这个结果,得到另一份数据,每个词都在哪些文件中包含着
  • 之后就是一个查询哈希表的过程
  • 主要的难点就是这个哈希表如何来

在未来实际工作中,也会用到一些“自定制的搜索引擎”

比如,我们自己的代码中,产生大量的日志,把这些日志导入到自己搭建的搜索引擎中,从而快速查找

  • 用到一些业界成熟的方案,比如 ES(倒排索引原理) 这种


相关文章
|
1月前
|
编解码 Java 程序员
【文件IO】文件内容操作
【文件IO】文件内容操作
47 2
|
1月前
|
存储 Java API
【文件IO】文件系统操作
【文件IO】文件系统操作
40 1
|
2月前
|
Java 大数据 API
Java 流(Stream)、文件(File)和IO的区别
Java中的流(Stream)、文件(File)和输入/输出(I/O)是处理数据的关键概念。`File`类用于基本文件操作,如创建、删除和检查文件;流则提供了数据读写的抽象机制,适用于文件、内存和网络等多种数据源;I/O涵盖更广泛的输入输出操作,包括文件I/O、网络通信等,并支持异常处理和缓冲等功能。实际开发中,这三者常结合使用,以实现高效的数据处理。例如,`File`用于管理文件路径,`Stream`用于读写数据,I/O则处理复杂的输入输出需求。
|
1月前
|
存储 Java 程序员
【Java】文件IO
【Java】文件IO
35 0
|
2月前
|
Linux C语言
C语言 文件IO (系统调用)
本文介绍了Linux系统调用中的文件I/O操作,包括文件描述符、`open`、`read`、`write`、`lseek`、`close`、`dup`、`dup2`等函数,以及如何获取文件属性信息(`stat`)、用户信息(`getpwuid`)和组信息(`getgrgid`)。此外还介绍了目录操作函数如`opendir`、`readdir`、`rewinddir`和`closedir`,并提供了相关示例代码。系统调用直接与内核交互,没有缓冲机制,效率相对较低,但实时性更高。
|
3月前
|
存储 监控 Linux
性能分析之从 IO 高定位到具体文件
【8月更文挑战第21天】性能分析之从 IO 高定位到具体文件
42 0
性能分析之从 IO 高定位到具体文件
|
3月前
IO流拷贝文件的几种方式
IO流拷贝文件的几种方式
36 1
|
4月前
|
Linux 数据处理 C语言
【Linux】基础IO----系统文件IO & 文件描述符fd & 重定向(下)
【Linux】基础IO----系统文件IO & 文件描述符fd & 重定向(下)
76 0
|
5月前
|
C++
Open3D File Io 文件IO
Open3D File Io 文件IO
|
4月前
|
Linux C语言 C++
【Linux】基础IO----系统文件IO & 文件描述符fd & 重定向(上)
【Linux】基础IO----系统文件IO & 文件描述符fd & 重定向(上)
54 0