Appearance
17.3 读取文本文件
读取文本文件的概念
读取文本文件是 Java IO 操作中的常见任务,它允许程序从文本文件中读取数据并进行处理。文本文件是指包含人类可读文本的文件,如 .txt、.java、.csv 等文件。
读取文本文件的方法
方法一:使用 FileReader
FileReader 是最基本的字符输入流,用于从文件中读取字符数据。
示例:使用 FileReader 读取文本文件
java
import java.io.FileReader;
import java.io.IOException;
public class ReadTextFileWithFileReader {
public static void main(String[] args) {
try (FileReader fr = new FileReader("example.txt")) {
int character;
while ((character = fr.read()) != -1) {
System.out.print((char) character);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}方法二:使用 BufferedReader
BufferedReader 是一个处理流,它包装了一个字符输入流,提供了缓冲功能和 readLine() 方法,提高读取效率。
示例:使用 BufferedReader 读取文本文件
java
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class ReadTextFileWithBufferedReader {
public static void main(String[] args) {
try (BufferedReader br = new BufferedReader(new FileReader("example.txt"))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}方法三:使用 Scanner
Scanner 类不仅可以用于读取用户输入,还可以用于读取文件内容。
示例:使用 Scanner 读取文本文件
java
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
public class ReadTextFileWithScanner {
public static void main(String[] args) {
try (Scanner scanner = new Scanner(new File("example.txt"))) {
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}方法四:使用 Files 类(Java 7+)
Java 7 引入了 Files 类,它提供了更简洁的方法来读取文件。
示例:使用 Files.readAllLines 读取文本文件
java
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
public class ReadTextFileWithFiles {
public static void main(String[] args) {
try {
List<String> lines = Files.readAllLines(Paths.get("example.txt"));
for (String line : lines) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}读取文本文件的常见操作
1. 逐行读取
逐行读取是读取文本文件的常见方式,适用于处理按行组织的数据。
java
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class ReadTextFileLineByLine {
public static void main(String[] args) {
try (BufferedReader br = new BufferedReader(new FileReader("example.txt"))) {
String line;
int lineNumber = 1;
while ((line = br.readLine()) != null) {
System.out.println("第 " + lineNumber + " 行: " + line);
lineNumber++;
}
} catch (IOException e) {
e.printStackTrace();
}
}
}2. 读取特定行
有时候我们只需要读取文件中的特定行。
java
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class ReadSpecificLine {
public static void main(String[] args) {
int targetLine = 5; // 要读取的行号
try (BufferedReader br = new BufferedReader(new FileReader("example.txt"))) {
String line;
int currentLine = 1;
while ((line = br.readLine()) != null) {
if (currentLine == targetLine) {
System.out.println("第 " + targetLine + " 行: " + line);
break;
}
currentLine++;
}
if (currentLine <= targetLine) {
System.out.println("文件没有第 " + targetLine + " 行");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}3. 统计文件行数
统计文件中的行数是一个常见的操作。
java
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class CountLines {
public static void main(String[] args) {
int lineCount = 0;
try (BufferedReader br = new BufferedReader(new FileReader("example.txt"))) {
while (br.readLine() != null) {
lineCount++;
}
System.out.println("文件共有 " + lineCount + " 行");
} catch (IOException e) {
e.printStackTrace();
}
}
}4. 读取文件内容到字符串
有时候我们需要将整个文件的内容读取到一个字符串中。
java
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
public class ReadFileToString {
public static void main(String[] args) {
try (BufferedReader br = new BufferedReader(new FileReader("example.txt"));
Writer writer = new StringWriter()) {
String line;
while ((line = br.readLine()) != null) {
writer.write(line);
writer.write(System.lineSeparator());
}
String content = writer.toString();
System.out.println("文件内容:\n" + content);
} catch (IOException e) {
e.printStackTrace();
}
}
}处理编码问题
问题描述
当读取文本文件时,可能会遇到编码问题,导致读取的内容出现乱码。
解决方案
使用 InputStreamReader 并指定正确的编码。
示例:指定编码读取文本文件
java
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
public class ReadTextFileWithEncoding {
public static void main(String[] args) {
try (BufferedReader br = new BufferedReader(
new InputStreamReader(new FileInputStream("example.txt"), StandardCharsets.UTF_8))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}示例:读取 CSV 文件
CSV(Comma-Separated Values)是一种常见的文本文件格式,用于存储表格数据。
java
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class ReadCSVFile {
public static void main(String[] args) {
try (BufferedReader br = new BufferedReader(new FileReader("data.csv"))) {
String line;
while ((line = br.readLine()) != null) {
// 分割 CSV 行
String[] fields = line.split(",");
System.out.println("姓名: " + fields[0] + ", 年龄: " + fields[1] + ", 成绩: " + fields[2]);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}常见问题
1. 文件不存在
症状:读取文件时抛出 FileNotFoundException
解决方案:确保文件路径正确,检查文件是否存在
2. 编码错误
症状:读取的内容出现乱码
解决方案:使用 InputStreamReader 并指定正确的编码
3. 内存不足
症状:读取大文件时抛出 OutOfMemoryError
解决方案:逐行读取文件,而不是一次性读取整个文件
4. 权限不足
症状:读取文件时抛出 SecurityException 或 AccessDeniedException
解决方案:确保程序有足够的权限访问文件
最佳实践
使用 try-with-resources:自动关闭流,避免资源泄漏
使用缓冲流:提高读取效率,特别是对于大文件
指定编码:处理文本文件时,指定正确的编码
逐行读取:对于大文件,使用逐行读取的方式,避免内存不足
错误处理:捕获并处理可能的异常
文件路径:使用相对路径时,注意当前工作目录
总结
读取文本文件是 Java IO 操作中的常见任务:
读取方法:
- FileReader:基本的字符输入流
- BufferedReader:带缓冲的字符输入流,提供 readLine() 方法
- Scanner:可以方便地读取文件内容
- Files 类:Java 7+ 提供的简洁方法
常见操作:
- 逐行读取
- 读取特定行
- 统计文件行数
- 读取文件内容到字符串
编码问题:
- 使用 InputStreamReader 并指定正确的编码
CSV 文件:
- 使用 split() 方法分割 CSV 行
通过合理使用这些方法,可以有效地读取和处理文本文件,满足不同场景的需求。
