上一篇
Java文件读写如何快速掌握
- 后端开发
- 2025-06-01
- 4825
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社区技术共识。