8.2 逐行读取与文本处理
一次性读取整个文件很简单,但真实文件可能很大。如果一个日志文件有几百万行,把它全部读入内存会很浪费。逐行读取可以一次处理一行。
BufferedReader
BufferedReader 会用缓冲区高效读取文本。它常通过 Files.newBufferedReader() 创建。
java
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
public class ReadLinesDemo {
public static void main(String[] args) throws IOException {
Path path = Path.of("quotes.txt");
try (BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
}
}reader.readLine() 会返回下一行文本,不包含换行符。读到文件末尾时,它会返回 null。
try (...) { ... } 这种写法叫 try-with-resources。代码块结束后,即使中途发生异常,reader 也会被自动关闭。
正在加载概念检查...
用 Scanner 读取 token
Scanner 可以按 token、按行或按数字读取文件。它对初学者很友好,但处理大文件时,BufferedReader 通常更快。
java
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.Scanner;
public class ScannerFileDemo {
public static void main(String[] args) throws IOException {
Path path = Path.of("numbers.txt");
try (Scanner scanner = new Scanner(path, StandardCharsets.UTF_8)) {
int total = 0;
while (scanner.hasNextInt()) {
total += scanner.nextInt();
}
System.out.println("总和:" + total);
}
}
}当文件格式简单、主要按 token 读取时,可以用 Scanner。当你需要完整控制每一行文本时,优先用 BufferedReader。
正在加载交互实验...
正在加载概念检查...
拆分单词
下面的程序读取 quotes.txt,去掉每个单词两端的标点,并把清理后的单词逐行写入 words.txt。在这个例子中,quotes.txt 内容是:
text
Talk is cheap. Show me the code.
Code never lies, comments sometimes do.
Stay Hungry Stay Foolish.java
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
public class WordExtractor {
static String cleanWord(String word) {
return word.replaceAll("^[\\p{Punct}]+|[\\p{Punct}]+$", "");
}
public static void main(String[] args) throws IOException {
Path input = Path.of("quotes.txt");
Path output = Path.of("words.txt");
try (
BufferedReader reader = Files.newBufferedReader(input, StandardCharsets.UTF_8);
BufferedWriter writer = Files.newBufferedWriter(output, StandardCharsets.UTF_8)
) {
String line;
while ((line = reader.readLine()) != null) {
String[] words = line.split("\\s+");
for (String word : words) {
String cleaned = cleanWord(word);
if (!cleaned.isEmpty()) {
writer.write(cleaned);
writer.newLine();
}
}
}
}
}
}同一个 try-with-resources 头部可以打开两个资源。Java 会自动关闭它们,并且按相反顺序关闭。
程序运行后,words.txt 变成:
text
Talk
is
cheap
Show
me
the
code
Code
never
lies
comments
sometimes
do
Stay
Hungry
Stay
Foolish正在加载概念检查...
正在加载本节练习...