本文最后更新于 2025-11-13,文章内容可能已经过时。

一、大文件处理

为什么需要特殊处理大文件?

  • 一次性加载大文件到内存会导致 OutOfMemoryError(内存溢出)
  • 文件过大时,系统I/O操作频繁,性能急剧下降

优化策略与实践

1. 使用缓冲流减少I/O次数
// 读取大文件(推荐使用BufferedReader,设置更大缓冲区)
try (BufferedReader reader = new BufferedReader(
        new FileReader("large_file.txt"), 64 * 1024)) { // 64KB缓冲区
    String line;
    while ((line = reader.readLine()) != null) {
        // 处理每一行数据,避免内存溢出
        processLine(line);
    }
}

性能对比

  • 用 FileInputStream 读 100MB 文件:约 10 万次 I/O 操作
  • 用 BufferedInputStream(8KB 缓冲区):约 1.2 万次 I/O 操作
  • 效率提升 8 倍以上
2. 按块读取(适合二进制文件)
// 处理超大二进制文件(如视频、图片)
try (FileChannel channel = FileChannel.open(Paths.get("huge_file.bin"))) {
    ByteBuffer buffer = ByteBuffer.allocate(1024 * 1024); // 1MB 缓冲
    while (channel.read(buffer) > 0) {
        buffer.flip(); // 准备读取
        // 处理 buffer 中的数据
        processBuffer(buffer);
        buffer.clear(); // 为下一次读取准备
    }
}
3. 避免一次性加载整个文件
  • 错误做法:List lines = Files.readAllLines(Paths.get("file.txt"));
  • 正确做法:逐行/逐块处理,避免内存溢出
4. 写入大文件优化
// 写入大文件,避免频繁flush
try (BufferedWriter writer = new BufferedWriter(
        new FileWriter("output.txt"), 64 * 1024)) {
    for (String data : dataList) {
        writer.write(data);
        writer.newLine();
    }
    // 仅在最后flush一次(除非需要实时落盘)
}
5. 多线程处理(注意数据顺序)
// 分割文件并并行处理
int numThreads = Runtime.getRuntime().availableProcessors();
List<Future<?>> futures = new ArrayList<>();
for (int i = 0; i < numThreads; i++) {
    int start = i * (fileSize / numThreads);
    int end = (i + 1) * (fileSize / numThreads);
    futures.add(executor.submit(() -> processFileChunk(start, end)));
}
// 等待所有线程完成
for (Future<?> future : futures) {
    future.get();
}