使用 Java BufferedReader 实现高效文本处理

JavaJavaBeginner
立即练习

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

介绍

在本实验中,我们将使用 Java 的 BufferedReader 类,它是 java.io 包的一部分。BufferedReader 用于从字符输入流中读取文本,并对字符进行缓冲以提高性能。该类封装了其他 reader 类和输入流,使我们能够提高程序的整体效率和性能。我们将探索 BufferedReader 的不同构造函数、方法和使用场景,以便更好地理解其功能。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL java(("`Java`")) -.-> java/StringManipulationGroup(["`String Manipulation`"]) java(("`Java`")) -.-> java/ObjectOrientedandAdvancedConceptsGroup(["`Object-Oriented and Advanced Concepts`"]) java(("`Java`")) -.-> java/FileandIOManagementGroup(["`File and I/O Management`"]) java/StringManipulationGroup -.-> java/stringbuffer_stringbuilder("`StringBuffer/StringBuilder`") java/ObjectOrientedandAdvancedConceptsGroup -.-> java/user_input("`User Input`") java/FileandIOManagementGroup -.-> java/files("`Files`") java/FileandIOManagementGroup -.-> java/read_files("`Read Files`") java/FileandIOManagementGroup -.-> java/io("`IO`") java/FileandIOManagementGroup -.-> java/stream("`Stream`") subgraph Lab Skills java/stringbuffer_stringbuilder -.-> lab-117473{{"`使用 Java BufferedReader 实现高效文本处理`"}} java/user_input -.-> lab-117473{{"`使用 Java BufferedReader 实现高效文本处理`"}} java/files -.-> lab-117473{{"`使用 Java BufferedReader 实现高效文本处理`"}} java/read_files -.-> lab-117473{{"`使用 Java BufferedReader 实现高效文本处理`"}} java/io -.-> lab-117473{{"`使用 Java BufferedReader 实现高效文本处理`"}} java/stream -.-> lab-117473{{"`使用 Java BufferedReader 实现高效文本处理`"}} end

使用 FileReader 创建 BufferedReader

BufferedReader 的构造函数接受一个 Reader 对象作为参数。我们可以使用 FileReader 创建一个 reader,FileReader 以默认编码读取文本文件。在这一步中,我们将通过封装 FileReader 来使用 BufferedReader 类读取文件。

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class BufferedReaderDemo {
    public static void main(String[] args) {
        String path = "path/to/your/file.txt";
        try {
            FileReader fileReader = new FileReader(path);
            BufferedReader bufferedReader = new BufferedReader(fileReader); //通过封装 FileReader 创建 BufferedReader
            // 在此处添加从文件中读取数据的代码

            bufferedReader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

要运行代码,请使用 javac BufferedReaderDemo.java 编译文件,然后使用 java BufferedReaderDemo 运行。

使用流创建 BufferedReader

我们也可以使用输入流作为数据源来创建 BufferedReader。在这一步中,我们将用 BufferedReader 封装 InputStreamReader,并从 System.in 读取数据。这将读取我们通过键盘输入的数据。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class BufferedReaderDemo {
    public static void main(String[] args) {
        try {
            InputStreamReader isr = new InputStreamReader(System.in);
            BufferedReader bufferedReader = new BufferedReader(isr); //创建 BufferedReader
            System.out.println("Enter Something:");
            String line = bufferedReader.readLine(); //从控制台读取输入
            System.out.println("You Entered: " + line); //打印输入内容

            bufferedReader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

关闭流

我们应该始终使用 BufferedReaderclose() 方法来释放与 reader 相关的所有系统资源。为了简化代码,我们可以使用 try-with-resources 块来自动关闭流。

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class BufferedReaderDemo {
    public static void main(String[] args) {
        String path = "path/to/your/file.txt";
        try (FileReader fileReader = new FileReader(path);
             BufferedReader bufferedReader = new BufferedReader(fileReader)) {

            // 在此处添加从文件中读取数据的代码

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

BufferedReader 与 Scanner 的比较

ScannerBufferedReader 都可以用于从外部源读取数据。然而,这两个类之间存在一些差异。在这一步中,我们将比较一些关键区别。

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.Scanner;

public class BufferedReaderDemo {
    public static void main(String[] args) {
        String path = "path/to/your/file.txt";
        try (FileReader fileReader = new FileReader(path);
             BufferedReader bufferedReader = new BufferedReader(fileReader);
             Scanner scanner = new Scanner(fileReader)) {
            long startTime = System.nanoTime();
            // 使用 BufferedReader 读取文件
            bufferedReader.readLine();
            while (bufferedReader.readLine() != null) ;
            long endTime = System.nanoTime();
            System.out.println("BufferedReader 耗时 : " + (endTime - startTime) + "ns");

            startTime = System.nanoTime();
            // 使用 Scanner 读取文件
            scanner.nextLine();
            while (scanner.hasNextLine()) scanner.nextLine();
            endTime = System.nanoTime();
            System.out.println("Scanner 耗时 : " + (endTime - startTime) + "ns");

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

这段代码比较了 BufferedReaderScanner 从同一文件中读取数据所花费的时间。时间会有所不同,但输出会告诉你哪个耗时更长。

逐行读取文件

BufferedReader 类提供了多种读取数据的方法。readLine() 方法一次读取一行数据。如果到达流的末尾,该方法会返回 null。在这一步中,我们将使用 BufferedReader.readLine() 读取文件。

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class BufferedReaderDemo {
    public static void main(String[] args) {
        String path = "path/to/your/file.txt";
        try (FileReader fileReader = new FileReader(path);
             BufferedReader bufferedReader = new BufferedReader(fileReader)) {

            String line;
            while ((line = bufferedReader.readLine()) != null) {
                System.out.println(line);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

从文件中读取单个字符

我们还可以使用 BufferedReader 类的 read() 方法一次读取一个字符。该方法将读取的字符作为整数返回。如果到达流的末尾,则返回 -1。

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class BufferedReaderDemo {
    public static void main(String[] args) {
        String path = "path/to/your/file.txt";
        try (FileReader fileReader = new FileReader(path);
             BufferedReader bufferedReader = new BufferedReader(fileReader)) {

            int charRead;
            while ((charRead = bufferedReader.read()) != -1) {
                System.out.print((char) charRead);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

从文件中读取多个字符

read() 方法可以一次读取多个字符。我们需要传递一个字符数组,用于存储读取的数据。同时,我们需要指定一个偏移量(offset),表示字符数组的起始索引,存储的数据将从该索引开始。此外,还需要指定要读取的最大字符长度。

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class BufferedReaderDemo {
    public static void main(String[] args) {
        String path = "path/to/your/file.txt";
        try (FileReader fileReader = new FileReader(path);
             BufferedReader bufferedReader = new BufferedReader(fileReader)) {

            char[] charArr = new char[5];
            bufferedReader.read(charArr, 0, 5);
            System.out.print(charArr);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

跳过字符

BufferedReader 类提供了一个 skip() 方法,可以用来跳过字符。它接受一个 long 类型的参数。

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class BufferedReaderDemo {
    public static void main(String[] args) {
        String path = "path/to/your/file.txt";
        try (FileReader fileReader = new FileReader(path);
             BufferedReader bufferedReader = new BufferedReader(fileReader)) {

            int charRead;
            StringBuilder sb = new StringBuilder();
            while ((charRead = bufferedReader.read()) != -1) {
                if (charRead != '*') {
                    sb.append((char) charRead);
                } else {
                    bufferedReader.skip(1);
                }
            }
            System.out.println(sb);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

标记与重置

BufferedReader 类提供了 mark() 方法,用于标记一个特定的字符。我们可以通过 reset() 方法随时返回到这个标记的字符。mark() 方法接受一个整数作为输入,表示在标记失效之前可以读取的最大字节数。

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class BufferedReaderDemo {
    public static void main(String[] args) {
        String path = "path/to/your/file.txt";
        try (FileReader fileReader = new FileReader(path);
             BufferedReader bufferedReader = new BufferedReader(fileReader)) {

            char[] charArr = new char[5];
            charArr[0] = (char) bufferedReader.read();
            charArr[1] = (char) bufferedReader.read();

            bufferedReader.mark(10);
            bufferedReader.skip(1);
            charArr[2] = (char) bufferedReader.read();
            charArr[3] = (char) bufferedReader.read();
            charArr[4] = (char) bufferedReader.read();
            System.out.println(charArr);

            bufferedReader.reset();
            char asterisk = (char) bufferedReader.read();
            System.out.print(asterisk);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

总结

在本实验中,我们使用 Java 的 BufferedReader 类从字符输入流中读取文本。我们学习了如何用 BufferedReader 包装其他 reader 类和输入流,以提高性能和效率。我们涵盖了从文件中读取单个和多个字符、跳过字符、标记和重置文件位置,以及比较 BufferedReaderScanner 类等主题。我们还使用了 try-with-resources 块来自动关闭流,避免内存泄漏。

您可能感兴趣的其他 Java 教程