• 文件操作及IO(java)


    前言

    在计算机中"文件"的概念很大,比如一些 .txt、.doc、.jpg、.mp4 等后缀的文件都叫作 普通文件。当然也有不普通的文件,比如:目录(也叫作目录文件)。同时在计算中也把一些硬件和软件资源给抽象成了文件等。(键盘、显示器等)

    而在我们程序员眼中只将文件分为了两类:文本文件 和 二进制文件

    文件文件 与 二进制文件 有什么不同?

    我们都知道 文本 其实也是由二进制组成,也就是说 文本文件 也是由 二进制 组成。

    那为什么要分为 两种文件?

    这是因为在文本文件中相邻的二进制之间是有联系的,大都是多个二进制组成一个字符,最终一个一个的字符形成了文本。(从肉眼上看不是乱码的字符)

    而二进制文件里面的二进制之间是没有联系的。

    最简单区分 文本文件 和 二进制文件 的方式:将一个文件使用 记事本 打开,如果是乱码就是 二进制文件,反之不是乱码就是 文本文件!!!

    在操作系统中管理文件是 “文件系统” 模块负责,而 文件系统 则是通过 树形结构 的方式来组织管理文件的。

    "此电脑"就是这颗树的根节点,而里面的 C盘、D盘等就相当于一棵棵的子树。(就相当于一棵N叉数)

    在组织完文件之后,为了能正确定位 每个文件的 位置,就有了 “路径”。

    路径分为 : 相对路径 / 绝对路径

    绝对路径就是开头从 盘符 开始的一条字符串:比如 F:\test.txt ( 描述了 text.txt 文件的位置 )

    相对路径则是以 .(当前路径) 或者 … (当前路径的父路径)开头。

    所以想要使用相对路径,就需要清楚哪个是 基准路径(也就是当前路径)

    那接下来我们就了解一些 java 中的有关文件(普通文件)的操作。

    1. Java中的文件操作

    我们知道在 java 中给我们提供了一些有关文件IO的操作。并将它们放在了 java.util.io 中。

    在这其中的文件操作大致分为两类:文件系统相关的操作 / 文件内容相关的操作(在C语言里也学过一些)

    1. 文件系统相关的操作

    这个是指通过 “文件资源管理器” 来完成一些操作。

    比如:新建文件夹(新建目录)、重命名、删除文件夹(删除目录)、创建文件、删除文件等。

    构造方法

    //所传的参数可以是 绝对路径 也可以是 相对路径
    File file = new File("f:/test.txt");
    
    • 1
    • 2

    普通方法(第一部分)

    public class Demo1 {
        public static void main(String[] args) throws IOException {
            //为了好观察效果,这里使用 相对路径
            File file = new File("./test.txt");
    
            //返回 file 的父目录文件路径
            String parent = file.getParent();
            System.out.println(parent);
    
            //返回 file 的纯文件名称
            String name = file.getName();
            System.out.println(name);
    
            //获取 file 的文件路径
            String path = file.getPath();
            System.out.println(path);
    
            //获取 file 的绝对路径
            String absolutePath = file.getAbsolutePath();
            System.out.println(absolutePath);
    
            //获取 file 对象修饰过的绝对路径  (通过运行结果就能观察到不同)
            String canonicalPath = file.getCanonicalPath(); //有 IO 异常
            System.out.println(canonicalPath);
    
            //判断 file 对象描述的文件是否存在
            boolean exists = file.exists();
            System.out.println(exists); //我并没有在 当前路径 下创建一个 test.txt 的文件,所以值应给为 false
    
            //判断当前 file 对对象描述的文件是否是一个目录文件
            boolean directory = file.isDirectory();
            System.out.println(directory);
    
            //判断当前文件是否是一个 普通文件
            boolean file1 = file.isFile();
            System.out.println(file1);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    普通方法(第二部分)

    public class Demo2 {
        public static void main(String[] args) throws IOException {
            File file = new File("f:/test.txt");
    
            //根据 file 对象创建一个 空文件 ,成功便返回 true,反之则是 false
            boolean newFile = file.createNewFile();
            System.out.println(newFile);
    
            //删除 file 对象路径下的文件,成功 true,反之则是 false
            //注意 该方法是 立即删除
            boolean delete = file.delete();
            System.out.println(delete);
            
            //这个方法也是删除文件 ,但它是 程序退出之后再删除
            file.deleteOnExit();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    普通方法(第三部分)

    public class Demo3 {
        public static void main(String[] args) {
    //        File file = new File("./aaa");
    
            File file = new File("./aaa/bbb/ccc/ddd");
    
    //        //创建一级目录
    //        boolean mkdir = file.mkdir();
    //        System.out.println(mkdir);
    
            //可以一下创建多级目录
            boolean mkdirs = file.mkdirs();
            System.out.println(mkdirs);
    
            //拿到当前目录下的所有文件名
            File file1 = new File("./");
            String[] list = file1.list();
            System.out.println(Arrays.toString(list));
    
            System.out.println("============================================");
            //效果一样,就是返回类型不同 为 File 类型
            File[] files = file1.listFiles();
            System.out.println(Arrays.toString(files));
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    普通方法(第四部分)

    public class Demo4 {
        public static void main(String[] args) {
            File file1 = new File("./aaa");
            File file2 = new File("./zzz");
    
            //将 file1 描述的文件 重命名 为 file2描述的文件
            boolean b = file1.renameTo(file2);
            System.out.println(b);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    2. 文件内容相关的操作

    我们在上面知道,程序员将普通文件分为两种 : 文本文件 / 二进制文件

    所以在这里 java 标准库中也给我们提供了 两种 系列操作: 字节流对象 / 字符流对象。

    而我们日常需要使用的一些操作都在里面:打开文件 、读文件、写文件、关闭文件。

    1. 字节流对象

    在字节流对象里,有关读和写的操作都在两个类里:InputStream(读) 和 OutputStream(写)。

    而这两个类都是接口(抽象类)。也就是说明在new对象的时候需要使用继承了这两个类的实例类,去真正实现里面的方法。

    1. InputStream(读)

    在java标准库中继承这个抽象类的实体类是 FileInputStream 。

    同时 FileInputStream 类中有一个 read() 方法,它可以从文件中读取字节。

    //read有三个重载方法
    
    //没有参数,返回值类型为 int 
    //表示每次读取一个字节用int类型返回
    public int read() throws IOException{...}//有一个字节数组参数,返回类型为 int ,这种参数我们称作 "输出型参数"
    //表示每次读取若干个字节的数据,并将数据存放到 byte[] 中(从下标为0处放),然后返回读取字节的个数。
    public int read(byte b[]) throws IOException {...}//有三个参数:字节数组、下标、长度,返回类型为 int
    //表示每次读取若干个字节的数据,并将数据存放到 byte[] 中(从下标 off 处开始放),然后返回读取字节的个数
    //len : 表示最多能放多少个元素在 byte[] 中,也就是能放多少个字节。
    public int read(byte b[], int off, int len) throws IOException {...}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    具体代码:

    public class Demo5 {
        public static void main(String[] args) throws FileNotFoundException {
            //提出来定义,好方便在 finally 里使用
            InputStream inputStream = null;
            try {
                //创建流对象
                inputStream = new FileInputStream("f:/test.txt");
                //一个一个字节的读取文件
                while(true){
                    int read = inputStream.read();
                    if(read == -1){
                        break;
                    }
                    //打印一下读取到的字节(字节所对应的int)
                    System.out.println(read);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                //写在 finally 里后,即使触发了异常,也会释放资源
                try {
                    //断言一下 inputStream 是否为 null
                    assert inputStream != null;
                    //还要记得释放资源
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    分析:这个代码虽然实现了读取文件中的数据,但是我们发现它实现的很繁琐,那么能不能简化一下呢?

    答案是肯定的,我们可以使用 try with resources 来进行简化

    try with resources 的作用就是可以帮助我们自动的进行资源的释放。

    但是注意在 try() 里创建的实例对象需要实现 Closeable接口,才能写在括号里面!!!

    简化后的代码:

    public class Demo6 {
        public static void main(String[] args) {
            //在括号里创建 输入流对象
            try(InputStream inputStream = new FileInputStream("f:/test.txt")){
                //用字节的方式循环读取文件中的数据
                while(true){
                    int read = inputStream.read();
                    //如果返回值为 -1,表示已经读到文件的末尾了。
                    //read返回的值范围 -1 ~ 255
                    if(read == -1){
                        break;
                    }
                    //打印一下这个字节
                    System.out.println(read);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    这时便可以很明显的看到代码简单了许多。


    当然在上面我们使用的是 没有参数的 read 方法,但是一般我们使用是 一个参数的read 方法,这样效率更高。

    具体代码:

    public class Demo7 {
        public static void main(String[] args) {
            try(InputStream inputStream = new FileInputStream("f:/test.txt")){
                while(true){
                    //用来存放每次读取的数据
                    byte[] bytes = new byte[1024];
                    int read = inputStream.read(bytes);
                    //判断是否读完了
                    if(read == -1){
                        break;
                    }
                    //循环打印 bytes 中的数据
                    for (int i = 0; i < read; i++) {
                        System.out.println(bytes[i]);
                    }
                    //可以将数据转换成一个字符串,并设置字符编码集
                    String str = new String(bytes,0,read,"utf-8");
                    System.out.println(str);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    2. OutputStream (写)

    在 java 标准库中继承了 OutputStream 的实体类是 FileOutputStream 。

    并且 FileOutputStream 中的方法使用也基本上与上面的大同小异。

    public class Demo8 {
        public static void main(String[] args) {
            //这样创建实例的话,每次打开文件后,就会将文件里的内容给清空。
            try(OutputStream outputStream = new FileOutputStream("f:/test.txt")){
                //想要追加写,就需要在 路径 后每添加一个参数 true,表示追加写
                //OutputStream outputStream = new FileOutputStream("f:/test.txt",true);
    
                //一个字节一个字节的写
                outputStream.write(97);
                outputStream.write(98);
                outputStream.write(99);
    
                //一次写入多个字节(大多使用这种方式)
                byte[] bytes = new byte[]{100,101,102};
                outputStream.write(bytes);
    
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    2. 字符流对象

    顾名思义,就是针对文本文件的读取和写入。(以字符为单位读写)

    它也有两个接口: Reader / Writer

    同时也有两个实体类来实现它们 FileReader / FileWriter。

    1. Reader(读)

    使用方法大同小异。

    //使用没有参数的 read 方法(每次读取一个字符)
    public class Demo9 {
        public static void main(String[] args) {
            try(Reader reader = new FileReader("f:/test.txt")){
                //每次读取一个字符,返回实际读取的字符的ASCII值。读完了返回 -1
                while(true){
                    int read = reader.read();
                    //判断是否读到了文件末尾
                    if(read == -1){
                        break;
                    }
                    //打印读到的数据
                    System.out.println((char)read);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    //使用一个参数的 read 方法(每次读取若干字符)
    public class Demo10 {
        public static void main(String[] args) {
            //创建字符流对象
            try(Reader reader = new FileReader("f:/test.txt")){
                while(true){
                    //使用字符数组来存储读取的数据
                    char[] ch = new char[1024];
                    int read = reader.read(ch);
                    //返回值为 -1 时,说明读到文件末尾了
                    if(read == -1){
                        break;
                    }
                    //循环打印每次读取的字符
                    for (int i = 0; i < read; i++) {
                        System.out.println(ch[i]);
                    }
                    //也可以直接将读到的数据转成一个字符串
                    String str = new String(ch,0,read);
                    System.out.println(str);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    2. Writer(写)

    public class Demo11 {
        public static void main(String[] args) {
            //和 OutputStream 的实现类一样,如果不多加一个 true 参数,则表示打开文件先清空然后写
            try(Writer writer = new FileWriter("f:/test.txt")){
                //写一个字符
                writer.write(97);
    
                //写一个字符串
                writer.write("hello word");
    
                //写一个字符数组
                char[] ch = new char[]{'a','a','a'};
                writer.write(ch);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    3. Scanner 和 InputStream 搭配使用

    我们以前在使用 Scanner 的时候,经常在实例化对象时传的参数时 System.in。这表示从键盘读取数据。

    在我们学习了 IO 和 文件 过后,我们可以将 Scanner 和 InputStream 搭配使用读取文本信息。

    具体代码:

    public class Demo19 {
        public static void main(String[] args) {
            StringBuilder stringBuilder = new StringBuilder();
            
            try(InputStream inputStream = new FileInputStream("f:/test.txt");
                Scanner scanner = new Scanner(inputStream,"utf-8")){
    
                //一行一行的读取数据
                while(scanner.hasNextLine()){
                    stringBuilder.append(scanner.nextLine());
                    //每读取一行就添加一个换行符
                    stringBuilder.append("\r\n");
                }
                
                //打印出读到的内容
                System.out.println(stringBuilder);
    
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    4. PrintWriter 、OutputStreamWriter 和 OutputStream 搭配使用

    这个相较于上面的 Scanner 和 InputStream 的搭配使用,是较为麻烦的。

    具体代码:

    public class Demo18 {
        public static void main(String[] args) {
            //true 表示是追加写,false/不加参数 表示不是追加写
            try(OutputStream outputStream = new FileOutputStream("f:/test.txt",true);
                OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream,"utf-8");
                PrintWriter printWriter = new PrintWriter(outputStreamWriter)){
    
                printWriter.print("fdag");
                printWriter.println("aaaa");
                printWriter.printf("\r\n%d 等于 %d 的绝对值。",5,-5);
    
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    2. 案例一

    题目:用户从键盘输入一个扫描路径和一个关键词,给该程序则可以在指定路径下查找名称包含关键词的普通文件,从而将它删除掉。

    步骤:

    • 接收用户输入的扫描文件路径和关键词。
    • 判断文件路径是否有误。
    • 通过递归的方式遍历该目录文件下的所有文件。
    • 递归遍历的同时判断每个普通文件的名称是否包含关键词。
    • 包含关键词就删除该文件。

    具体代码:

    public class Demo15 {
        public static void main(String[] args) {
            Scanner scanner = new Scanner(System.in);
            System.out.println("请输入需要扫描的路径:");
            String srcPath = scanner.next();
            System.out.println("请输入需要查找的文件名中的关键字:");
            String word = scanner.next();
    
            //1.检查路径是否正确
            File file = new File(srcPath);
            if(!file.isDirectory()){
                System.out.println("扫描路径有误!");
                return;
            }
    
            //2.遍历所有的文件并进行查找删除操作
            findAll(file,word);
        }
    
        private static void findAll(File file, String word) {
            //1.先拿到文件列表,并检查是否为空
            File[] files = file.listFiles();
            if(files == null){
                return;
            }
    
            //2.判断是否是普通文件,然后执行相应的操作
            for (File f : files) {
                if(f.isFile()){
                    if(f.getName().contains(word)){
                        //3.删除操作
                        delete(f);
                    }
                }else if(f.isDirectory()){
                    findAll(f,word);
                }
            }
        }
    
        private static void delete(File f) {
            Scanner scanner = new Scanner(System.in);
            try {
                //1.确认是否真正删除该文件
                System.out.println(f.getCanonicalPath()+" 是否确认删除该文件(Y/N):");
                String inputStr = scanner.next();
                //2.判断输入的是否为 Y/y
                if(inputStr.equals("Y")||inputStr.equals("y")){
                    //3.删除文件,并返回结果
                    boolean delete = f.delete();
                    //4.通过结果提示是否删除成功!
                    if(delete){
                        System.out.println("删除成功!");
                    }else{
                        System.out.println("删除失败!!!");
                    }
                }else{
                    System.out.println("取消删除!");
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64

    2. 案例二

    题目:普通文件的复制,用户输入一个普通文件的路径和一个复制文件到的目的地。通过程序进行复制操作。

    步骤:

    • 接收用户输入的源文件路径和目的地路径。
    • 判断源文件路径是否正确。
    • 通过 IO 和 文件 中的读和写操作,完成文件的复制。

    具体代码:

    public class Demo16 {
        public static void main(String[] args) {
            Scanner scanner = new Scanner(System.in);
            System.out.println("请输入拷贝源:");
            String srcPath = scanner.next();
            System.out.println("请输入目的地路径:");
            String destPath = scanner.next();
    
            //1.检查拷贝源是不是一个普通文件路径
            File file = new File(srcPath);
            if(!file.isFile()){
                System.out.println("拷贝源路径输入有误!");
                return;
            }
    
            //2.读取文件内容并写入到目的地
            readToWriter(file,destPath);
        }
    
        private static void readToWriter(File file,String destPath) {
            //1.先读后写
            try(InputStream inputStream = new FileInputStream(file);
                OutputStream outputStream = new FileOutputStream(destPath)){
    
                byte[] bytes = new byte[1024];
                while(true){
                    int len = inputStream.read(bytes);
                    //检查是否读到了文件末尾
                    if(len == -1){
                        break;
                    }
                    //将内容写到目的地
                    outputStream.write(bytes,0,len);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    3.案例三

    题目:用户输入一个文件目录和关键词。通过该程序遍历该目录下所有的普通文件,并判断每个普通文件中是否包含指定的关键词,包含就将该文件的路径打印在控制台上。

    步骤:

    • 接收用户输入的路径和关键词。
    • 判断输入的路径是否有误。
    • 遍历该路径下的所有文件,并判断其中的普通文件的内容中是否包含关键词。包含就打印文件路径。

    具体代码:

    public class Demo17 {
        public static void main(String[] args) throws IOException {
            Scanner scanner = new Scanner(System.in);
            System.out.println("请输入扫描路径:");
            String srcPath = scanner.next();
            System.out.println("请输入内容关键字:");
            String word = scanner.next();
    
            //1.检查扫描路径是否有误
            File file = new File(srcPath);
            if(!file.isDirectory()){
                System.out.println("扫描路劲有误!");
                return;
            }
    
            //2.循环遍历该路径下所有的文件内容,并进行判定
            findAll(file,word);
        }
    
        private static void findAll(File file, String word) throws IOException {
            //1.拿到当前目录下所有的文件
            File[] files = file.listFiles();
            if(files == null){
                return;
            }
    
            //2.判断相应的情况,并做出对应的操作
            for (File f:files) {
                //判断是否是一个普通文件
                if(f.isFile()){
                    //3.检查其中内容是否包含关键字
                    boolean flag = check(f, word);
                    if(flag){
                        //包含就打印该文件的路径
                        System.out.println(f.getCanonicalPath());
                    }
                }else if(f.isDirectory()){
                    findAll(f,word);
                }
            }
        }
    
        private static boolean check(File f, String word) {
            StringBuilder stringBuilder = new StringBuilder();
            //1.读取文件中的内容到 stringBuilder 中。
            try(InputStream inputStream = new FileInputStream(f);
                Scanner scanner = new Scanner(inputStream,"utf-8")){
    
                //一行一行的读取
                while(scanner.hasNextLine()){
                    //添加每一行的内容
                    stringBuilder.append(scanner.nextLine());
                    //添加换行符
                    stringBuilder.append("\r\n");
                }
    
            } catch (IOException e) {
                e.printStackTrace();
            }
    		//2.判断文件内容中是否包含关键词。(能找到 indexOf 返回下标,不能则返回-1)
            return stringBuilder.indexOf(word) != -1;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64

    4.刷新缓冲区(了解)

    .flush 就是刷新缓冲区的操作。

    什么是缓冲区?为什么需要?什么叫刷新缓冲区?

    缓冲区就是一块空间,它可以提高程序的运行效率。

    举个例子:搬石头

    一种方式:(效率很低)

    • 我每次搬起一块就走到目的地,然后放下。

    另一种方式 :(效率较高)

    • 我有一个盆(缓冲区),我每先将石头往盆里放,直到盆放满了。然后我就将盆搬到目的地去。如此反复,最后我发现石头搬完了,但是还有一盆没装满。即使如此,这时我还是要将没装满的盆给搬到目的地去(这个过程就是刷新缓冲区)

    为什么上面的代码中我们没有手动的 .flush 操作,完成缓冲区的刷新?

    • 在上面的代码中我们使用的是 try with resources ,这样就可以自动的调用 .close 操作(前提是需要实现 Closeable 接口)。这样就很方便。
    • 这是在上面说过的,同时我们还要知道,.close 操作其实就会调用 .flush 。也就是说它会自动的完成刷新缓冲区。这就是我们在上面不手动 .flush 的原因。
  • 相关阅读:
    【AI 测试】分词器
    2023-2028中国稻谷行业市场 国稻种芯:未来趋势预测报告
    ActiveReports.NET 16.2RPX 部分报告的完全支持
    如何让项目开发提速?
    【Java刷题】初始化List应该选择ArrayList还是LinkedList
    【C++ 学习 ㉘】- 详解 C++11 的列表初始化
    【计算机网络】第四章.网络层 网络层超硬核复习好物(1),考前必看!!
    python基于BAC0库进行bacnet IP的读写
    WSL2最佳实践,淘汰难用的Xshell和Finalshell
    【微信小程序】开发入门篇(一)
  • 原文地址:https://blog.csdn.net/m0_52066789/article/details/125461220