Java处理大CSV文件报OutOfMemoryHeapSpace错误求助
Java CSV大文件处理堆内存溢出解决方案
问题根因
你当前代码触发OOM的核心原因是调用了CSVReader.readAll()方法,该方法会将整个CSV文件的全部内容一次性加载到JVM堆内存的List<String[]>集合中,当文件体积超过JVM堆内存分配上限时就会抛出内存溢出错误,中等体积文件因为内存可容纳所以运行正常。
修复代码
改用流式逐行处理逻辑,全程不加载整个文件到内存,仅保留单行数据的内存占用,可支持任意体积的CSV文件处理:
package routines; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import au.com.bytecode.opencsv.CSVReader; import au.com.bytecode.opencsv.CSVWriter; public class RemoveLineBreakFromCsvHelper { public static void updateCSV (String fileToUpdate) throws IOException { File inputFile = new File(fileToUpdate); File tempFile = new File(fileToUpdate + ".tmp"); // 用try-with-resources自动关闭流,避免资源泄漏 try (CSVReader reader = new CSVReader(new FileReader(inputFile), ';'); CSVWriter writer = new CSVWriter(new FileWriter(tempFile), ';')) { String[] row; // 逐行读取,不会加载全量数据到内存 while ((row = reader.readNext()) != null) { // 处理当前行每个字段的换行符 for (int j = 0; j < row.length; j++) { if (row[j] != null) { // 同时处理\r\n、\r、\n三种换行格式,比原逻辑更严谨 row[j] = row[j].replaceAll("[\\r\\n]", ". "); } } // 处理完直接写入临时文件 writer.writeNext(row); } } // 全量处理完成后替换原文件,避免中途异常损坏原文件 if (inputFile.delete()) { tempFile.renameTo(inputFile); } System.out.println("CSV文件换行符处理完成"); } }
优化点说明
- 取消了全量数据存储的
List<String[]>,内存占用仅和单行数据大小相关,不会随文件体积增长 - 新增临时文件过渡逻辑,只有全部数据处理完成后才会替换原文件,避免处理中途报错导致原文件损坏
- 采用
try-with-resources语法自动管理IO流关闭,避免手动关闭遗漏导致的资源泄漏 - 优化了换行符匹配逻辑,可同时处理Windows(\r\n)、Mac(\r)、Linux(\n)三种系统的换行格式
内容的提问来源于stack exchange,提问作者maa aam
相关产品推荐
相关产品推荐

