每日程炼-IOUtils 单元(4): TDirectory.GetDirectories获取子目录

和 TDirectory.GetFiles 用法一样,

TDirectory.GetDirectories 是用来获取子目录的.

另外还有 TDirectory.GetFileSystemEntries 可同时获取文件与子目录, 用法都一样.

Demo下载:IOUnit4

和 TDirectory.GetFiles 用法一样, TDirectory.GetDirectories 是用来获取子目录的.

另外还有 TDirectory.GetFileSystemEntries 可同时获取文件与子目录, 用法都一样.

15:50:28.339 [main] DEBUG com.alibaba.excel.metadata.property.ExcelHeadProperty - The initialization sheet/table 'ExcelHeadProperty' is complete , head kind is NONE 15:50:28.366 [main] DEBUG com.alibaba.excel.context.AnalysisContextImpl - Initialization 'AnalysisContextImpl' complete java.lang.OutOfMemoryError: Java heap space Dumping heap to java_pid30672.hprof ... Heap dump file created [1102448651 bytes in 1.777 secs] Exception in thread "main" com.alibaba.excel.exception.ExcelAnalysisException: java.lang.OutOfMemoryError: Java heap space at com.alibaba.excel.analysis.ExcelAnalyserImpl.<init>(ExcelAnalyserImpl.java:61) at com.alibaba.excel.ExcelReader.<init>(ExcelReader.java:30) at com.alibaba.excel.read.builder.ExcelReaderBuilder.build(ExcelReaderBuilder.java:214) at com.alibaba.excel.read.builder.ExcelReaderBuilder.sheet(ExcelReaderBuilder.java:251) at com.alibaba.excel.read.builder.ExcelReaderBuilder.sheet(ExcelReaderBuilder.java:243) at com.soyotec.unixde.dtm.common.impl.datafile.handler.ExcelDataHandler.readPage(ExcelDataHandler.java:38) at com.soyotec.unixde.dtm.common.impl.datafile.Test.main(Test.java:27) Caused by: java.lang.OutOfMemoryError: Java heap space at java.util.Arrays.copyOf(Arrays.java:3236) at java.io.ByteArrayOutputStream.grow(ByteArrayOutputStream.java:118) at java.io.ByteArrayOutputStream.ensureCapacity(ByteArrayOutputStream.java:93) at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:153) at org.apache.poi.util.IOUtils.toByteArray(IOUtils.java:155) at org.apache.poi.util.IOUtils.toByteArray(IOUtils.java:121) at org.apache.poi.util.IOUtils.toByteArray(IOUtils.java:108) at org.apache.poi.openxml4j.util.ZipArchiveFakeEntry.<init>(ZipArchiveFakeEntry.java:47) at org.apache.poi.openxml4j.util.ZipInputStreamZipEntrySource.<init>(ZipInputStreamZipEntrySource.java:53) at org.apache.poi.openxml4j.opc.ZipPackage.openZipEntrySourceStream(ZipPackage.java:210) at org.apache.poi.openxml4j.opc.ZipPackage.openZipEntrySource
最新发布
03-26
<think>好的,我现在需要解决用户在处理Excel文件时遇到的OutOfMemoryError问题。用户提到了使用Alibaba EasyExcel和Apache POI时出现Java堆空间内存不足的错误。首先,我得回忆一下这两种工具的不同之处,以及为什么会出现内存问题。 Apache POI的传统方式,比如HSSF和XSSF,在处理大文件时确实容易内存溢出,因为它们会把整个文件加载到内存里,生成DOM树结构。尤其是XSSF处理xlsx文件时,数据量大时TreeMap存储行数据会占用很多内存。POI官方推荐使用SAX事件驱动模型来解决,比如XSSF和SAX结合的方式,这样逐行读取,不一次性加载整个文件,可以节省内存。不过用户可能已经知道这一点,但问题仍然存在,或者他们在使用POI时没有正确应用SAX方式。 而Alibaba的EasyExcel设计初衷就是为了解决POI的内存问题,采用逐行解析的流式读取,并且通过回调机制处理数据,这样内存占用会小很多。但用户提到在使用EasyExcel时也出现了OutOfMemoryError,这可能是因为他们在使用过程中没有正确配置或者代码中存在内存泄漏。例如,如果在回调方法中累积了所有数据,而没有及时处理或释放,仍然会导致内存增加。 接下来,我需要考虑用户可能遇到的几种情况。首先,确认他们是否真的正确使用了EasyExcel的流式读取。比如,是否在读取时没有将数据全部缓存到内存中,而是逐行处理。其次,检查JVM的堆内存设置是否足够,或者是否有必要增加堆大小。不过增加堆内存只是临时解决方案,最佳实践应该是优化代码。 另外,可能的问题点包括:在读取Excel时,使用了不适当的监听器,导致数据累积;在处理数据时,大量对象被创建且未被及时GC回收;或者Excel文件本身确实极大,即使使用流式读取,处理过程中生成的数据结构也可能占用过多内存。例如,如果每行数据都被转换成对象并存入一个List,那么这个List会不断增长,最终导致OOM。 解决方案方面,针对POI,用户需要切换到SAX模式,如使用XSSF和SAX API,或者使用SXSSF来写文件,因为它支持流式写入。对于EasyExcel,需要确保监听器在处理数据时及时释放资源,避免在内存中保存所有数据。例如,处理完一行后立即写入数据库或进行其他处理,而不是累积到集合中。 此外,调整JVM参数也是一个方向,比如增加-Xmx的值,但这只是临时措施,不能根治问题。还需要检查代码中是否有内存泄漏,例如静态集合持有了数据引用,导致无法被GC回收。使用分析工具如VisualVM或MAT可以帮助定位内存泄漏点。 用户提供的引用中提到EasyExcel是为了解决POI内存问题而设计的,所以理论上使用EasyExcel应该能避免OOM,但实际应用中可能因为使用方式不当导致问题。例如,用户可能在监听器中错误地存储了所有读取到的行数据,而不是逐行处理。因此,指导用户正确实现监听器,确保不累积数据是关键。 总结来说,解决这个问题需要分步骤:首先确认是否正确使用流式读取;其次检查代码是否有内存累积点;然后调整JVM参数;最后考虑文件拆分或其他内存优化手段。此外,对于POI用户,切换到SAX或SXSSF是必要的,而EasyExcel用户需要确保监听器的正确实现。</think>要解决Java程序处理Excel文件时出现的`java.lang.OutOfMemoryError: Java heap space`问题,需结合工具特性优化内存使用。以下是具体解决方案: --- ### 1. **Apache POI的优化方案** **问题根源** 传统POI(如`XSSFWorkbook`)会将整个Excel文件加载为内存中的树结构,导致大文件处理时内存飙升[^1]。 **解决方法** - **使用SAX事件驱动模式**: 逐行解析文件,避免全量加载。示例代码: ```java OPCPackage pkg = OPCPackage.open(new File("large.xlsx")); XSSFReader reader = new XSSFReader(pkg); XMLReader parser = XMLReaderFactory.createXMLReader(); parser.setContentHandler(new SheetHandler()); // 自定义处理逻辑 parser.parse(reader.getSheet("rId1")); ``` - **SXSSF流式写入**: 适用于导出大文件,限制内存中保留的行数: ```java SXSSFWorkbook workbook = new SXSSFWorkbook(100); // 仅保留100行在内存 ``` --- ### 2. **Alibaba EasyExcel的正确使用** **核心优势** EasyExcel通过逐行解析和回调机制,显著降低内存占用[^2]。 **关键配置** - **避免在监听器中累积数据**: 示例中若在`invoke()`方法中将所有数据存入`List`,会导致内存溢出: ```java public class DataListener extends AnalysisEventListener<MyData> { private List<MyData> cachedData = new ArrayList<>(); // 错误做法 @Override public void invoke(MyData data, AnalysisContext context) { cachedData.add(data); // 数据累积导致OOM } } ``` **正确做法**: 逐行处理或分批次处理后立即释放: ```java @Override public void invoke(MyData data, AnalysisContext context) { processAndSave(data); // 处理完立即释放引用 } ``` --- ### 3. **JVM参数调整** 增加堆内存大小(临时方案): ```bash java -Xmx4g -jar your_app.jar ``` 但需注意:仅适用于文件稍大的场景,无法彻底解决极端情况。 --- ### 4. **其他优化策略** - **分块处理**: 将Excel文件按行拆分为多个小文件处理。 - **排查内存泄漏**: 使用VisualVM或MAT分析堆转储,检查是否有静态集合持有数据引用。 - **升级依赖版本**: 确保EasyExcel或POI为最新版本,修复已知内存问题。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值