395. Java 文件操作基础 - 读写小文件
在 Java 的文件 I/O API 中,Files 工具类为我们提供了多种读写文件的方式。不同方法适用于不同场景。我们要学会“对症下药”,选择合适的方法。
1️⃣ 如何选择合适的 I/O 方法?
下面的表格总结了常见方法及使用场景:
| 读取 | 写入 | 适用场景 / 说明 |
|---|---|---|
readAllBytes() readAllLines() | write() | 最简单的用法:一次性读入或写出小文件(几 KB ~ 几 MB)。 |
newBufferedReader() | newBufferedWriter() | 逐行处理文本:适合处理大文本文件,避免一次性加载。 |
newInputStream() | newOutputStream() | 兼容 java.io:适合需要与传统 I/O 代码(如 InputStream、OutputStream)交互的场景。 |
newByteChannel() SeekableByteChannel ByteBuffer | —— | 高阶操作:适合随机访问文件,或需要 NIO 特性(非阻塞 I/O)。 |
FileChannel | —— | 高级应用:文件锁、内存映射(Memory-Mapped I/O),通常用于大文件处理。 |
2️⃣ 常见示例
🔹 读取整个文件内容
Path file = Paths.get("data.txt");
// 方式1:一次性读入所有字节(适合小文件)
byte[] bytes = Files.readAllBytes(file);
String content = new String(bytes, StandardCharsets.UTF_8);
// 方式2:一次性读入所有行
List<String> lines = Files.readAllLines(file, StandardCharsets.UTF_8);
lines.forEach(System.out::println);
👉 适用场景:配置文件、小日志文件、测试数据。
🔹 写入小文件
Path file = Paths.get("output.txt");
String content = "Hello, world!";
// 一次性写入
Files.write(file, content.getBytes(StandardCharsets.UTF_8));
👉 适用场景:快速保存结果文件、配置导出。
🔹 使用 BufferedReader / BufferedWriter(逐行读写)
Path file = Paths.get("data.txt");
// 逐行读取
try (BufferedReader reader = Files.newBufferedReader(file, StandardCharsets.UTF_8)) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
// 写入文件(逐行)
try (BufferedWriter writer = Files.newBufferedWriter(file, StandardCharsets.UTF_8)) {
writer.write("Line 1");
writer.newLine();
writer.write("Line 2");
}
👉 适用场景:大文件(避免一次性加载到内存)、日志分析、逐行转换。
🔹 使用 InputStream / OutputStream(兼容 java.io)
Path file = Paths.get("image.png");
// 读
try (InputStream in = Files.newInputStream(file)) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = in.read(buffer)) != -1) {
System.out.println("Read " + bytesRead + " bytes");
}
}
// 写
try (OutputStream out = Files.newOutputStream(Paths.get("copy.png"))) {
out.write(Files.readAllBytes(file));
}
👉 适用场景:和旧的 java.io 代码兼容,二进制文件处理(图片、视频)。
3️⃣ 进阶:文件属性(POSIX)
创建文件时,可以指定初始属性,例如文件所有者、组、权限(仅支持 POSIX 文件系统,如 Linux / macOS)。
Set<PosixFilePermission> perms = PosixFilePermissions.fromString("rw-r-----");
FileAttribute<Set<PosixFilePermission>> attr = PosixFilePermissions.asFileAttribute(perms);
Path file = Files.createFile(Paths.get("secure.txt"), attr);
👉 在安全敏感的场景(如日志、证书文件),可以确保文件一开始就有合适的权限。
🎯 总结
- 小文件 →
readAllBytes()/write()(最简单,适合小数据)。 - 大文件 →
BufferedReader/BufferedWriter(逐行处理)。 - 二进制 / 与老代码兼容 →
InputStream/OutputStream。 - 高性能 / 特殊需求 →
FileChannel、ByteBuffer、文件锁、内存映射。 - POSIX 属性 →
createFile()时传入FileAttribute。
👉 记住一句话:根据文件大小和用途选择 API,不要“无脑全用 readAllBytes()”,否则可能会内存爆炸 💥。