上一篇
Java文件读写如何快速掌握
- 后端开发
- 2025-06-01
- 2856
Java文件读写可通过
java.io或
java.nio包实现,使用
FileReader/FileWriter处理文本,
FileInputStream/FileOutputStream处理二进制数据,或用NIO的
Files.write()和
Files.readAllLines()简化操作,务必使用try-with-resources确保资源关闭。
Java文件读写详解:从基础到高效实践
文件操作是Java开发中的核心技能,无论是处理配置文件、日志记录还是数据持久化都离不开文件读写,本文将深入探讨Java文件读写的多种实现方式,并提供最佳实践方案。
传统的文件读写方式
使用FileInputStream/FileOutputStream读写二进制文件
// 写入二进制文件
try (FileOutputStream fos = new FileOutputStream("image.jpg")) {
byte[] data = new byte[1024];
int bytesRead;
while ((bytesRead = sourceStream.read(data)) != -1) {
fos.write(data, 0, bytesRead);
}
} catch (IOException e) {
e.printStackTrace();
}
// 读取二进制文件
try (FileInputStream fis = new FileInputStream("data.bin")) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
// 处理二进制数据
}
} catch (IOException e) {
e.printStackTrace();
}
使用FileReader/FileWriter处理文本文件
// 写入文本文件
try (FileWriter writer = new FileWriter("output.txt")) {
writer.write("Hello, 世界!n");
writer.append("第二行内容");
} catch (IOException e) {
e.printStackTrace();
}
// 读取文本文件
try (FileReader reader = new FileReader("input.txt")) {
char[] buffer = new char[1024];
int charsRead;
while ((charsRead = reader.read(buffer)) != -1) {
System.out.println(new String(buffer, 0, charsRead));
}
} catch (IOException e) {
e.printStackTrace();
}
使用Buffered提升IO性能
缓冲流显著提升IO效率,通过减少物理磁盘操作次数优化性能:
// 高效文本读取
try (BufferedReader br = new BufferedReader(new FileReader("largefile.txt"))) {
String line;
while ((line = br.readLine()) != null) {
// 处理每行内容
}
} catch (IOException e) {
e.printStackTrace();
}
// 高效文本写入
try (BufferedWriter bw = new BufferedWriter(new FileWriter("log.txt", true))) { // true表示追加模式
bw.write("2025-11-15 INFO: Application started");
bw.newLine();
} catch (IOException e) {
e.printStackTrace();
}
Java NIO(New I/O)高效文件操作
Java 7引入的NIO.2 API提供了更现代的文件操作方式:
Paths和Files类
Path path = Paths.get("data", "docs", "report.txt"); // 跨平台路径
// 读取所有行
List<String> lines = Files.readAllLines(path, StandardCharsets.UTF_8);
// 写入文件
Files.write(path, "新内容".getBytes(), StandardOpenOption.APPEND);
// 创建临时文件
Path tempFile = Files.createTempFile("prefix_", ".tmp");
使用Files.newBufferedReader/BufferedWriter
try (BufferedReader reader = Files.newBufferedReader(path)) {
reader.lines().forEach(System.out::println);
}
try (BufferedWriter writer = Files.newBufferedWriter(path,
StandardOpenOption.CREATE,
StandardOpenOption.APPEND)) {
writer.write("追加内容");
}
字符编码处理
正确处理字符编码避免乱码问题:
// 指定编码读取
try (InputStreamReader isr = new InputStreamReader(
new FileInputStream("data.txt"), "GBK")) {
// 处理GBK编码文件
}
// 指定编码写入
try (OutputStreamWriter osw = new OutputStreamWriter(
new FileOutputStream("output.txt"), StandardCharsets.UTF_8)) {
osw.write("UTF-8编码内容");
}
异常处理与资源管理
正确的异常处理保证资源释放:
Path source = Paths.get("source.txt");
Path target = Paths.get("backup.txt");
try (InputStream in = Files.newInputStream(source);
OutputStream out = Files.newOutputStream(target)) {
byte[] buffer = new byte[8192];
int length;
while ((length = in.read(buffer)) > 0) {
out.write(buffer, 0, length);
}
} catch (NoSuchFileException e) {
System.err.println("文件不存在: " + e.getFile());
} catch (AccessDeniedException e) {
System.err.println("无访问权限: " + e.getFile());
} catch (IOException e) {
System.err.println("IO错误: " + e.getMessage());
}
文件操作最佳实践
- 资源管理:始终使用try-with-resources自动关闭资源
- 缓冲使用:处理大文件必须使用缓冲流
- 路径处理:使用Paths.get()替代字符串拼接
- 异常处理:区分不同异常类型针对性处理
- NIO优先:新项目优先选择NIO.2 API
- 编码明确:始终指定字符编码格式
- 文件锁:多进程写入时使用FileLock
try (RandomAccessFile raf = new RandomAccessFile("data.dat", "rw"); FileLock lock = raf.getChannel().lock()) { // 安全写入操作 }
完整文件处理示例
public class FileProcessor {
public static void main(String[] args) {
Path input = Paths.get("input.csv");
Path output = Paths.get("report.txt");
try {
// 处理CSV并生成报告
processData(input, output);
System.out.println("文件处理完成");
} catch (IOException e) {
System.err.println("处理失败: " + e.getMessage());
}
}
private static void processData(Path input, Path output) throws IOException {
Map<String, Integer> dataMap = new HashMap<>();
// 读取CSV文件
try (Stream<String> lines = Files.lines(input)) {
lines.skip(1) // 跳过标题行
.map(line -> line.split(","))
.filter(fields -> fields.length >= 3)
.forEach(fields -> {
String key = fields[0] + "-" + fields[1];
int value = Integer.parseInt(fields[2]);
dataMap.merge(key, value, Integer::sum);
});
}
// 写入统计结果
try (BufferedWriter writer = Files.newBufferedWriter(output)) {
writer.write("分类,总计n");
dataMap.forEach((k, v) -> {
try {
writer.write(k + "," + v + "n");
} catch (IOException e) {
throw new UncheckedIOException(e);
}
});
}
}
}
不同场景技术选型指南
| 场景 | 推荐方案 | 优点 |
|---|---|---|
| 小文本读取 | Files.readAllLines() | 代码简洁 |
| 大文本处理 | BufferedReader | 内存友好 |
| 二进制文件 | BufferedInputStream/OutputStream | 性能稳定 |
| 结构数据处理 | Scanner类 | 解析方便 |
| 随机访问 | RandomAccessFile | 灵活定位 |
| 高并发场景 | FileChannel | 并发性能好 |
掌握Java文件读写需要根据具体需求选择合适的技术方案:
- 优先使用Java NIO.2(Files和Paths类)
- 处理大文件时务必采用缓冲机制
- 始终指定字符编码避免乱码
- 使用try-with-resources确保资源释放
- 重要操作添加异常恢复机制
随着Java版本迭代,Files工具类提供了越来越多简洁高效的API,建议持续关注官方更新,掌握如Files.readString()/writeString()(Java 11+)等新特性,不断提升文件操作效率与代码质量。
权威引用: 基于Oracle官方文档《Java I/O Tutorial》和《Java NIO.2 Guide》,遵循Java 17 LTS版本规范,核心API来自java.io和java.nio.file官方包,最佳实践参考自《Effective Java》第三版(Joshua Bloch著)和Java社区技术共识。
