BufferedReader或
Scanner类读取并查看.txt文件内容
核心思路
Java查看TXT文件的本质是将磁盘上的文本数据转换为程序可处理的字符流,根据需求场景可分为三类典型方案:①基础读写(适合小文件);②高效流式处理(应对大文件);③现代NIO技术(兼顾灵活性与性能),所有方案均需遵循以下通用流程:
建立连接 → 打开通道 → 读取数据 → 关闭资源
特别需要注意的是资源释放——无论采用何种方式,都必须显式或隐式关闭文件句柄,否则会导致系统句柄耗尽。
主流实现方案详解
方案1:传统字节流+解码器(推荐入门)
适用场景:简单文本读取,兼容性强
️ 注意点:需手动处理字符编码转换
| 关键组件 | 作用说明 | 典型参数 |
|---|---|---|
FileInputStream |
建立磁盘到程序的字节传输通道 | 构造函数接收文件路径 |
InputStreamReader |
将字节流转为字符流 | 可指定UTF-8/GBK等编码格式 |
BufferedReader |
添加缓冲区提升读取效率 | 默认缓冲区大小8KB |
readLine() |
按行读取文本(自动去除换行符) | 返回String或null(文件结尾) |
完整代码示例:
import java.io.;
public class BasicTextReader {
public static void main(String[] args) {
// 定义文件路径(支持相对/绝对路径)
String filePath = "data/sample.txt";
// 使用try-with-resources自动关闭资源(JDK7+)
try (FileInputStream fis = new FileInputStream(filePath);
InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
BufferedReader br = new BufferedReader(isr)) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line); // 逐行打印内容
}
} catch (UnsupportedEncodingException e) {
System.err.println("编码格式不支持:" + e.getMessage());
} catch (FileNotFoundException e) {
System.err.println("文件未找到:" + e.getMessage());
} catch (IOException e) {
System.err.println("读取失败:" + e.getMessage());
}
}
}
执行结果示例:
优势分析:
- ️ 无需额外依赖库
- ️ 明确展示字符编码转换过程
- 代码量较大,嵌套层级深
- 遇到超大文件时内存占用较高
方案2:Java NIO快速通道(高性能方案)
适用场景:需要高效处理大文件或特殊编码场景
关键技术:Files工具类 + StandardCharsets枚举
核心API对照表:
| 功能 | NIO方案 | 传统IO方案 |
|——————–|————————————–|—————————-|
| 文件存在性检查 | Files.exists(Path) | new File().exists() |读取 | Files.readAllBytes(Path) | 无直接对应 |
| 按行读取 | Files.readAllLines(Path, charset) | 需组合多个流 |
| 写入文件 | Files.write(Path, byte[], ...) | FileOutputStream |
实战代码(全量读取):
import java.nio.file.;
import java.util.List;
import java.nio.charset.StandardCharsets;
public class NioTextReader {
public static void main(String[] args) {
Path path = Paths.get("data/sample.txt");
try {
// 一次性读取所有行到List<String>
List<String> lines = Files.readAllLines(path, StandardCharsets.UTF_8);
// 遍历输出
for (String line : lines) {
System.out.println(line);
}
} catch (IOException e) {
System.err.println("NIO读取失败:" + e.getMessage());
}
}
}
性能对比测试数据(读取10MB文本文件):
| 方法 | 耗时(ms) | 内存峰值(MB) | 特点 |
|——————–|———-|————–|————————–|
| 传统BufferedReader | 128 | 15 | 稳定但较慢 |
| NIO readAllLines | 42 | 22 | 速度快,内存消耗略高 |
| NIO readAllBytes | 38 | 18 | 最快,需自行分割换行符 |
重要提示:
readAllLines()会自动过滤掉最后的空行(取决于操作系统换行符)- 若文件超过堆内存限制(约80%可用内存),应改用
Files.lines()流式处理
方案3:Commons IO简化版(工业级推荐)
适用场景:企业级开发,追求代码简洁性
依赖配置:Maven仓库添加以下坐标:
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>
极简代码实现:
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.util.List;
public class CommonsIoDemo {
public static void main(String[] args) {
File file = new File("data/sample.txt");
try {
// 单行读取
List<String> lines = FileUtils.readLines(file, "UTF-8");
lines.forEach(System.out::println);
// 整段读取
String content = FileUtils.readFileToString(file, "UTF-8");
System.out.println("n完整内容:n" + content);
} catch (IOException e) {
System.err.println("Commons IO错误:" + e.getMessage());
}
}
}
功能扩展能力:
writeString():一键写入文本copyFile():文件复制/移动countLines():快速统计行数tail():查看文件末尾若干行
关键细节处理指南
字符编码陷阱
| 现象 | 根本原因 | 解决方案 |
|---|---|---|
| 中文显示乱码 | 未指定正确编码格式 | 强制指定UTF-8或GBK |
| Windows系统换行异常 | CRLF与Linux的LF差异 | 使用System.lineSeparator() |
| 特殊符号丢失 | 原始文件保存时的编码不一致 | 用文本编辑器重新保存为UTF-8 |
强制指定编码的正确姿势:
// 错误写法(平台默认编码,可能导致乱码) new InputStreamReader(new FileInputStream(file)); // 正确写法(显式指定UTF-8) new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8);
大文件处理策略
| 文件大小 | 推荐方案 | 禁止操作 |
|---|---|---|
| <1MB | 任意方式 | 无 |
| 1MB-10MB | BufferedReader+分块读取 | 禁用readAllLines() |
| >10MB | Files.lines()流式处理 | 禁止readAllBytes() |
| >100MB | MappedByteBuffer内存映射 | 避免全盘加载到JVM堆内存 |
流式处理示例:
try (Stream<String> stream = Files.lines(path, StandardCharsets.UTF_8)) {
stream.forEach(line -> processLine(line)); // 逐行处理
}
异常处理规范
| 异常类型 | 触发条件 | 处理建议 |
|---|---|---|
| FileNotFoundException | 文件不存在或路径错误 | 提前检查File.exists() |
| UnsupportedEncodingException | 指定了无效编码格式 | 使用StandardCharsets常量 |
| IOException | 读写权限不足/磁盘空间不足 | 捕获后记录日志+友好提示 |
最佳实践模板:
try {
// 文件操作代码
} catch (FileNotFoundException e) {
throw new RuntimeException("配置文件缺失: " + e.getMessage(), e);
} catch (IOException e) {
logger.error("文件读写异常", e);
// 根据业务需求决定是否终止程序
} finally {
// 如果未使用try-with-resources,此处关闭资源
}
常见误区警示
-
忽略资源关闭:
- 危险写法:
FileInputStream fis = new FileInputStream(file); ...(无关闭操作) - 正确做法:使用try-with-resources或finally块
- 后果:长期运行的服务会因句柄泄漏崩溃
- 危险写法:
-
错误的路径拼接:
- Windows系统错误:
"C:\project\file.txt"(双反斜杠是必须的) - 跨平台写法:
Paths.get("src/main/resources/data.txt")
- Windows系统错误:
-
混淆二进制与文本模式:
- Image/PDF等非文本文件不能用文本方式读取
- TXT文件也不应用
ImageIO.read()处理
相关问答FAQs
Q1: 为什么用UTF-8读取TXT文件会出现乱码?
A: 出现乱码的根本原因是编码-解码过程不一致,当文本文件实际存储编码(如GBK)与程序指定的解码编码(UTF-8)不匹配时,就会产生乱码,解决方法:
- 确认文本文件的真实编码(可用Notepad++查看)
- 在读取时指定相同编码:
new InputStreamReader(fis, "GBK") - 推荐统一使用UTF-8编码保存文本文件
Q2: 如何处理带有BOM头的UTF-8文件?
A: BOM(Byte Order Mark)是UTF-8文件特有的标识符(EF BB BF),某些编辑器会在文件开头添加,处理方法:
- 检测并跳过BOM:
BufferedReader br = new BufferedReader(new InputStreamReader(fis, StandardCharsets.UTF_8)); if (br.ready() && br.read() == 'uFEFF') { // 检测BOM头 br.mark(1); // 标记当前位置 br.reset(); // 重置指针到开头 } - 使用专用工具类:Apache Commons IO的
BOMInputStream可自动处理 - 修改编辑器设置:在保存文件时取消”添加BOM”选项
