Java使用Apache POI读取10000个Excel文件并合并为一个主文件
Java批量读取Excel并生成汇总报表方案
我之前处理过类似的批量Excel汇总需求,针对你要处理10000个文件的场景,非常推荐用EasyExcel来实现——它比传统的Apache POI更节省内存,能有效避免大文件场景下的内存溢出问题,适配海量文件的批量处理。下面是完整的落地方案:
一、先准备依赖
如果你用Maven,直接在pom.xml里添加EasyExcel的核心依赖:
<!-- EasyExcel 核心依赖(版本可以选最新稳定版) --> <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>3.3.2</version> </dependency>
二、定义数据实体类
假设所有源Excel的结构是一致的(比如包含姓名、部门、业绩这几个字段),先写一个实体类和Excel列做映射:
import com.alibaba.excel.annotation.ExcelProperty; import lombok.Data; // 用Lombok的@Data简化getter/setter,也可以自己手写 @Data public class ExcelData { @ExcelProperty("姓名") // 对应Excel表头的"姓名"列 private String name; @ExcelProperty("部门") private String department; @ExcelProperty("业绩") private Double performance; }
三、编写逐行处理的监听器
EasyExcel采用监听器模式逐行读取数据,不会把整个Excel加载到内存里,这对处理10000个文件至关重要。我们可以在监听器里每积累一批数据就写入汇总表,避免内存积压:
import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.event.AnalysisEventListener; import com.alibaba.excel.ExcelWriter; import java.util.ArrayList; import java.util.List; public class ExcelDataListener extends AnalysisEventListener<ExcelData> { // 每攒1000行就写入一次汇总表,这个数值可以根据内存情况调整 private static final int BATCH_COUNT = 1000; private List<ExcelData> dataList = new ArrayList<>(BATCH_COUNT); private final ExcelWriter excelWriter; // 构造方法传入汇总表的写入器 public ExcelDataListener(ExcelWriter excelWriter) { this.excelWriter = excelWriter; } // 每读取一行数据就触发这个方法 @Override public void invoke(ExcelData data, AnalysisContext context) { dataList.add(data); if (dataList.size() >= BATCH_COUNT) { writeBatchData(); dataList.clear(); // 清空列表,释放内存 } } // 整个文件读取完成后触发,处理最后一批剩余数据 @Override public void doAfterAllAnalysed(AnalysisContext context) { writeBatchData(); } // 批量写入汇总表的方法 private void writeBatchData() { excelWriter.write(dataList, EasyExcel.writerSheet("汇总数据").build()); } }
四、主逻辑:遍历源文件夹并生成汇总表
最后写主方法,遍历源文件夹下的所有Excel文件,逐个读取并写入到目标汇总表中:
import com.alibaba.excel.EasyExcel; import com.alibaba.excel.ExcelWriter; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; public class ExcelMerger { public static void main(String[] args) { // 替换成你的源文件夹路径和目标文件路径 String sourceDirPath = "/your/source/folder/path"; String targetFilePath = "/your/target/folder/path/汇总报表.xlsx"; // 用try-with-resources自动关闭写入器,避免资源泄漏 try (ExcelWriter excelWriter = EasyExcel.write(new FileOutputStream(targetFilePath), ExcelData.class).build()) { File sourceDir = new File(sourceDirPath); if (!sourceDir.isDirectory()) { System.err.println("错误:源路径不是有效的文件夹!"); return; } // 过滤出文件夹下的所有.xlsx/.xls文件 File[] excelFiles = sourceDir.listFiles((dir, name) -> { String lowerName = name.toLowerCase(); return lowerName.endsWith(".xlsx") || lowerName.endsWith(".xls"); }); if (excelFiles == null || excelFiles.length == 0) { System.err.println("提示:源文件夹中没有找到Excel文件!"); return; } // 遍历所有Excel文件进行处理 for (File excelFile : excelFiles) { System.out.println("正在处理文件:" + excelFile.getName()); // 读取当前文件,用自定义监听器逐行写入汇总表 EasyExcel.read(excelFile, ExcelData.class, new ExcelDataListener(excelWriter)).sheet().doRead(); } System.out.println("汇总报表生成完成!文件路径:" + targetFilePath); } catch (IOException e) { e.printStackTrace(); System.err.println("生成汇总表时出现异常:" + e.getMessage()); } } }
五、关键注意事项
- 内存安全:监听器的批量写入机制能保证即使处理10000个文件,内存也不会爆掉,这是处理海量文件的核心。
- 异常容错:可以在遍历文件时单独加try-catch,避免单个文件读取失败导致整个流程中断。
- 性能优化:如果想更快处理,可以用线程池并行读取文件,但要注意:EasyExcel的
ExcelWriter不是线程安全的,所以每个线程需要单独处理文件,最后再合并结果(或者用同步块控制写入)。 - 表头兼容:如果源文件的表头和实体类的
@ExcelProperty不匹配,可以用索引(比如@ExcelProperty(index = 0))来对应列,适配不同的表头名称。
内容的提问来源于stack exchange,提问作者user1302909
相关产品推荐
相关产品推荐

