上一篇
java io怎么读取文本数据并保存
- 后端开发
- 2025-08-04
- 2261
Scanner
类读取文本数据,用
PrintWriter
或
BufferedWriter
将数据写入文件,通过
File
对象指定路径完成操作
Java中,IO(Input/Output)操作是处理文件读写的核心机制,以下是关于如何读取文本数据并保存的详细讲解,涵盖多种实现方式、代码示例及注意事项:
读取文本数据的常用方法
基础字符流:FileReader
- 原理:直接基于字符编码逐字符或批量读取文本内容,适合简单场景。
File file = new File("input.txt"); try (FileReader fr = new FileReader(file)) { int ch; while ((ch = fr.read()) != -1) { // 单次读一个字符 System.out.print((char) ch); } } catch (IOException e) { e.printStackTrace(); }
上述代码通过
read()
逐个读取字符直到返回-1
(文件末尾),若需提高效率,可改用数组缓冲:char[] buffer = new char[1024]; int len; while ((len = fr.read(buffer)) != -1) { // 批量读取到缓冲区 String part = new String(buffer, 0, len); // 处理part逻辑... }
- 特点:无需手动转换编码,默认使用平台默认字符集;但缺乏灵活性控制编码格式。
带缓冲的字符流:BufferedReader
- 优势:内置缓存区减少频繁磁盘访问,显著提升性能,常与
FileReader
组合使用:try (BufferedReader br = new BufferedReader(new FileReader("largefile.log"))) { String line; while ((line = br.readLine()) != null) { // 按行读取 System.out.println(line); } } catch (IOException e) { e.printStackTrace(); }
readLine()
方法会自动丢弃换行符,适用于日志分析等逐行处理场景。
NIO方式:Files工具类(Java 7+)
- 简洁性:静态方法直接加载全部内容到内存,适合小型文件:
List<String> lines = Files.readAllLines(Paths.get("poem.txt")); for (String line : lines) { System.out.println(line); } // 或读取为单个字符串 String content = new String(Files.readAllBytes(Paths.get("note.txt")), StandardCharsets.UTF_8);
- 注意:大文件慎用此方式,可能导致内存溢出。
保存文本数据的实现方案
基础写入:FileWriter
- 基本用法:覆盖模式写入单一字符串:
try (FileWriter fw = new FileWriter("output.txt")) { fw.write("Hello World"); } catch (IOException e) { e.printStackTrace(); }
追加模式需设置构造函数第二个参数为
true
:new FileWriter("app.log", true).write("New log entryn"); // 追加日志
- 局限性:无缓冲机制,频繁落盘影响性能。
高效缓冲写入:BufferedWriter
- 最佳实践:结合缓冲区批量刷新数据:
try (BufferedWriter bw = new BufferedWriter(new FileWriter("report.doc"))) { bw.write("Section 1:..."); bw.newLine(); // 跨平台换行符处理 bw.write("Section 2:..."); } catch (IOException e) { e.printStackTrace(); }
newLine()
会根据系统自动适配n
或rn
,比直接写入"n"
更可靠。
字节级转换写入
- 适用场景:需要精确控制编码时(如UTF-8转GBK):
// 写入阶段:字符串→字节数组→文件 byte[] utf8Data = "中文测试".getBytes(StandardCharsets.UTF_8); try (FileOutputStream fos = new FileOutputStream("chinese_text.dat")) { fos.write(utf8Data); } // 读取阶段:反向解码验证完整性 byte[] storedBytes = Files.readAllBytes(Paths.get("chinese_text.dat")); String validatedStr = new String(storedBytes, StandardCharsets.UTF_8); assert validatedStr.equals("中文测试");
此模式常用于跨系统兼容的数据交换。
关键注意事项对比表
维度 | FileReader/FileWriter | BufferedReader/BufferedWriter | Files类 |
---|---|---|---|
性能 | 低(无缓冲) | 高(默认8KB缓存) | 极高(全量加载) |
适用文件大小 | 小型 | 中小型 | 仅限小型 |
编码可控性 | 依赖默认编码 | 同左 | 可指定Charset参数 |
API友好度 | 基础易上手 | 需管理缓冲区 | 最简捷 |
异常安全性 | 需手动close | try-with-resources推荐 | 自动资源释放 |
完整示例:带编码指定的文本复制工具
import java.io.; import java.nio.charset.StandardCharsets; public class TextCopier { public static void main(String[] args) throws IOException { File src = new File("source.txt"); File dest = new File("copy.txt"); try (Reader reader = new InputStreamReader(new FileInputStream(src), StandardCharsets.UTF_8); Writer writer = new OutputStreamWriter(new FileOutputStream(dest), StandardCharsets.UTF_8)) { char[] buffer = new char[4096]; int bytesRead; while ((bytesRead = reader.read(buffer)) != -1) { writer.write(buffer, 0, bytesRead); } } } }
该实现确保了:
① 显式指定UTF-8编码避免乱码;
② 使用NIO转换流统一处理字节/字符转换;
③ try-with-resources语法保证资源释放。
FAQs
Q1: 为什么有时读取中文会出现乱码?如何处理?
A: 因为未正确设置字符集,解决方案是在创建流时明确指定编码格式,new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8)
,读取时应使用相同的编码解析字节数组。
Q2: 大文件处理时内存不足怎么办?
A: 采用分块读取策略,例如每次读取固定大小的缓冲区(如4KB),而不是一次性加载整个文件,可通过循环控制单次I/O的数据量,配合缓冲流