注册网站后邮箱收到邮件,自己做网站服务器,网站文章页的排名怎么做,有没有专门做美食的网站✅如何针对大Excel做文件读取#xff1f; #x1f7e9;如何针对大Excel做文件读取#x1f7e9;XSSFWorkbook文件读取#x1f7e9;EasyExcel文件读取 ✅扩展知识#x1f7e9; EasyExcel简介#x1f7e9;EasyExcel 为什么内存占用小#xff1f; #x1f7e9;如何针对大Ex… ✅如何针对大Excel做文件读取 如何针对大Excel做文件读取XSSFWorkbook文件读取EasyExcel文件读取 ✅扩展知识 EasyExcel简介EasyExcel 为什么内存占用小 如何针对大Excel做文件读取
在POI中提供了SXSSFWorkbook通过将部分数据写入磁盘上的临时文件来减少内存占用。但是SXSSFWorkbook只能用于文件写入但是文件读取还是不行的就像我们前面分析过的Excel的文件读取还是会存在内存溢出的问题的。
参考本人博客文件处理专栏: 什么是POI为什么他会导致内存溢出
参考本人博客文件处理专栏: POI如何做大文件的写入
那如果要解决这个问题可以考虑使用EasyExcel。
EasyExcel是一个基于Java的、快速、简洁、解决大文件内存溢出的Excel处理工具。他能让你在不用考虑性能、
内存的等因素的情况下快速完成Excel的读、写等功能。关于使用XSSFWorkbook和EasyExcel的文件读取我这里也做了个内存占用的对比
XSSFWorkbook文件读取
读取一个27.3MB的文件文件的生成代码✅链接: POI如何做大文件的写入
package excel.read;import org.apache.poi.ss .usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class XSSFExcelReadTest {public static void main(String[] args) {// 指定要读取的文件路径String filename example.xlsx;try (FileInputStream fileInputStream new FileInputStream(new File(filename))) {// 创建工作簿对象Workbook workbook new XSSFWorkbook(fileInputStream);//获取第一个工作表Sheet sheet workbook.getSheetAt(0);// foreach 遍历所有行for (Row row : sheet) {// 遍历所有单元格for (Cell cell : row) {// 根据不同数据类型处理数据switch (cel1.getCel1Type()) {case STRING:System.out.print(cell.getstringCellValue() t);break;case NUMERIC:if (DateUtil.isCellDateFormatted(cell)) {System.out.print(cell.getDateCellValue() t);} else {System.out.print(cell.getNumericCellValue() t”);}break;case BOOLEAN:System.out.print(cell.getBooleanCellValue() t);break;case FORMULA:System.out.print(cell.getCellFormula() t);break;default:System.out.print();}}System.out.println();//换行}}catch (IOException e) {e.printStackTrace();}}
}同样使用Arthas查看内存占用情况 占用内存1000M
EasyExcel文件读取
package excel.read;import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener:public class EasyExcelReadTest {public static void main(Stringl] args) {// 指定要读取的文件路径String filename example.xlsx;EasyExcel.read(filename, new PrintDataListener()).sheet().doRead();}
}// 监听器用于处理读取到的数据
class PrintDatalistener implements ReadListenerObject {Overridepublic void invoke(Object data, AnalysisContext context) {//处理每一行的数据System.out.println(data) ;}Overridepublic void doAfterAllAnalysed(AnalysisContext context) {// 所有数据解析完成后的操作}Overridepublic void onException(Exception exception, AnalysisContext context) throws Exception {//处理读取过程中的异常}
}同样使用Arthas查看内存占用情况 内存占用只有不到100MB。
✅扩展知识 EasyExcel简介
EasyExcel是一款软件程序允许用户创建、编辑和分析电子表格。它设计成用户友好和直观使得所有技能水平的用户都能轻松处理数据。EasyExcel提供了广泛的功能包括进行计算、创建图表和图形以及在表格中组织数据的能力。它还支持各种文件格式如.xls和.xlsx使用户能够方便地导入和导出来自其他应用程序的数据。总体而言EasyExcel是一种多功能的工具用于管理和操作电子表格格式的数据。
EasyExcel 为什么内存占用小
EasyExcel是一款基于POIApache开源的Java类库开发的Excel操作工具。相比于传统的操作Excel的方式EasyExcel采用了一种新的处理方式即将Excel数据转化为对象列表然后进行操作。这种方式减少了对内存的占用提高了数据处理的效率。
具体的来说EasyExcel在内存占用方面有以下几个优势
1. 逐行读写EasyExcel通过逐行读写的方式操作Excel即一次只读取或写入一行数据而不是一次性读取或写入整个文件。这样可以大大减少对内存的占用。
2. 分段读写当需要处理大文件时EasyExcel可以将文件拆分成多个小段进行读写每次只处理一小段数据将读写的内存压力均匀分散降低了内存的占用。
3. 内存缓冲区EasyExcel内部使用了内存缓冲区来存储读取或写入的数据通过合理控制缓冲区的大小可以有效地减少对内存的占用。
4. 高效的数据处理算法EasyExcel内部采用了高效的数据处理算法例如使用零拷贝技术来提高数据读写的速度减少对内存的占用。
综上所述EasyExcel通过优化读写方式、使用内存缓冲区和高效的数据处理算法等手段可以实现在相同数据量的情况下占用更小的内存空间提高数据处理的效率。
参考代码展示了如何使用EasyExcel读取Excel文件并计算内存占用。
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.read.listener.ReadListener;import java.io.File;public class EasyExcelMemoryDemo {public static void main(String[] args) {String filePath path/to/excel/file.xlsx;// 创建一个监听器用于统计内存占用ReadListenerObject listener new ReadListener() {private long startMemory;Overridepublic void invoke(Object data, AnalysisContext context) {if (context.readRowHolder().getRowIndex() 0) {// 记录读取第一行数据时的内存占用startMemory Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();}}Overridepublic void doAfterAllAnalysed(AnalysisContext context) {// 读取完所有数据后计算内存占用的差值long endMemory Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();long memoryUsage endMemory - startMemory;System.out.println(Excel文件读取完毕);System.out.println(内存占用差值 memoryUsage bytes);}};// 读取Excel文件EasyExcel.read(new File(filePath)).registerReadListener(listener).sheet().doRead();}
}
输出Excel文件读取完毕后的内存占用差值。相比于使用传统的POI工具使用EasyExcel读取Excel文件时内存占用会更小。
EasyExcel是一个Java库用于简化Excel文件的读写操作。相较于Apache POI等传统Excel处理库EasyExcel具有内存占用小的优势。这主要归功于EasyExcel的底层实现和数据处理方式。
展示
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.metadata.BaseRowModel;
import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.WriteTable;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy; import java.util.ArrayList;
import java.util.List; /***author 昕宝爸爸爱编程*date 23/12/14*/
public class AdvancedMemoryOptimizedExample { public static void main(String[] args) { String inputFileName input_example_complex.xlsx; String outputFileName output_example_complex.xlsx; int pageSize 1000; int sheetCount 3; // 定义要写入的Sheet数量 int totalPage 0; // 总页数变量用于动态计算总页数 // 创建数据模型类用于存储读取到的数据 class DataModel extends BaseRowModel { private String field1; // 字段1 private int field2; // 字段2 // 其他字段... // 对应的getter和setter方法... } // 内存优化示例读取Excel文件并分页处理 ListDataModel dataList new ArrayList(); // 创建一个空的列表用于存储数据 ExcelReader excelReader EasyExcel.read(inputFileName, new NoModelDataListenerDataModel()).build(); // 使用自定义的DataModel类作为监听器的参数类型 ReadSheet readSheet EasyExcel.readSheet(pageSize).build(); // 设置读取时的分页参数 excelReader.read(readSheet, new AnalysisEventListenerDataModel() { // 使用自定义的DataModel类作为事件处理接口的参数类型 Override public void invoke(DataModel data, AnalysisContext context) { // 在invoke方法中进行自定义数据处理逻辑比如将读取到的数据存储到数据库等操作... dataList.add(data); // 这里仅作示例将读取到的数据添加到列表中实际应用中可能需要进行其他处理 } Override public void doAfterAllAnalysed(AnalysisContext context) { // 处理读取完所有数据后的逻辑...可以在这里添加一些操作比如关闭资源等 totalPage context.getHead().getSheet().getVirtual(context).getTotalRowNum() / pageSize 1; // 动态计算总页数用于后续写入操作时使用 } }); // 开始读取数据并传入监听器进行数据处理 excelReader.finish(); // 读取完成后关闭Excel读取器 // 内存优化示例写入Excel文件并自定义样式和分页写入策略 WriteCellStyle contentWriteCellStyle new WriteCellStyle(); // 创建一个自定义的单元格样式对象可以根据需要设置样式属性 HorizontalCellStyleStrategy horizontalCellStyleStrategy new HorizontalCellStyleStrategy(null, contentWriteCellStyle); // 创建一个水平单元格样式策略对象用于设置单元格样式策略 ExcelWriterBuilder writerBuilder EasyExcel.write(outputFileName); // 创建Excel写入器构建器对象用于配置写入参数和设置样式策略等 writerBuilder.registerWriteHandler(horizontalCellStyleStrategy); // 注册之前创建的样式策略对象到写入器中用于设置单元格样式策略 ExcelWriter excelWriter writerBuilder.build(); // 创建Excel写入器实例用于实际写入操作 for (int i 1; i sheetCount; i) { // 根据定义的Sheet数量循环创建多个Sheet进行写入操作 WriteSheet writeSheet EasyExcel.writerSheet(Sheet i).build(); // 创建多个Sheet进行写入操作每个Sheet名称分别为Sheet1、Sheet2等可以根据需要自定义Sheet名称和数量等参数 excelWriter.write(dataList, writeSheet, totalPage); // 将之前读取到的数据写入到输出文件中并传入Sheet参数和样式策略等参数同时传入动态计算的总页数参数用于分页写入操作时使用 } // 循环写入多个Sheet数据到输出文件中并传入对应的样式策略和总页数参数等主要通过以下几个方式来节省内存
使用分页读取和写入通过设置pageSize参数将数据分页读取和写入可以减少一次性读取和写入的数据量从而减少内存占用。
使用数据模型类通过创建一个数据模型类DataModel将读取到的数据存储到该类的对象中而不是直接存储到原始数据类型列表中。这样可以避免为每个数据项创建过多的对象从而减少内存占用。
使用水平单元格样式策略通过创建一个水平单元格样式策略对象HorizontalCellStyleStrategy并将样式策略注册到Excel写入器中。该策略可以根据单元格的内容自动应用样式从而减少手动设置样式所带来的内存开销。
动态计算总页数在读取完所有数据后通过调用context.getHead().getSheet().getVirtual(context).getTotalRowNum()方法动态计算总页数。这样可以避免在循环中多次计算总页数从而减少内存占用。
综上所述通过分页读取和写入、使用数据模型类、使用水平单元格样式策略以及动态计算总页数等方式实现了内存的优化使用。