美文网首页
POI和EasyExcel比较

POI和EasyExcel比较

作者: Lolipiza | 来源:发表于2022-05-11 21:42 被阅读0次

POI:

1.userModel模式
一种是使用最多的,像用的HSSFWorkBook、XSSFWorkBook、SXSSFWorkBook,这里我们称它为(也是内存消耗较大的模式)。为什么内存占用大呢?直接看读取源码,拿XSSFWorkbook加载为例,最终会调用这个方法:

public ZipInputStreamZipEntrySource(ThresholdInputStream inp) throws IOException {
   zipEntries = new ArrayList<FakeZipEntry>();
   boolean going = true;
   while(going) {
      ZipEntry zipEntry = inp.getNextEntry();
      if(zipEntry == null) {
         going = false;
      } else {
         FakeZipEntry entry = new FakeZipEntry(zipEntry, inp);
         inp.closeEntry();
         zipEntries.add(entry);
      }
   }
   inp.close();
}

这里就可以看到,会一直读流,每行都会生成一个对象,加载到zipEntries中去,这就是内存占用大的根本原因。

2.eventModel模式
也就是SAX模式,easyexcel就是重写了poi的这个方法,达到更小的内存占用。通过将流一行行的读取,加载到内存,达到节约内存的目的。


EasyExcel:

XlsxSaxAnalyser将数据读取成inputStream流,缓存到了sheetMap

public XlsxSaxAnalyser(AnalysisContext analysisContext, InputStream decryptedStream) throws Exception {
        ...
        //将每sheet数据读取成inputStream流,缓存sheetMap
        XSSFReader xssfReader = new XSSFReader(pkg);
        analysisUse1904WindowDate(xssfReader, readWorkbookHolder);

        stylesTable = xssfReader.getStylesTable();
        sheetList = new ArrayList<ReadSheet>();
        sheetMap = new HashMap<Integer, InputStream>();
        XSSFReader.SheetIterator ite = (XSSFReader.SheetIterator)xssfReader.getSheetsData();
        int index = 0;
        if (!ite.hasNext()) {
            throw new ExcelAnalysisException("Can not find any sheet!");
        }
        while (ite.hasNext()) {
            InputStream inputStream = ite.next();
            sheetList.add(new ReadSheet(index, ite.getSheetName()));
            sheetMap.put(index, inputStream);
            index++;
        }
    }

拿到一行数据后,会去调用dealData方法,dealData方法会去调用之初始化的监听器,执行业务处理,readListener.invoke方法。

public class RowTagHandler extends AbstractXlsxTagHandler {
    @Override
    public void startElement(XlsxReadContext xlsxReadContext, String name, Attributes attributes) {
        XlsxReadSheetHolder xlsxReadSheetHolder = xlsxReadContext.xlsxReadSheetHolder();
        int rowIndex = PositionUtils.getRowByRowTagt(attributes.getValue(ExcelXmlConstants.ATTRIBUTE_R),
            xlsxReadSheetHolder.getRowIndex());
        Integer lastRowIndex = xlsxReadContext.readSheetHolder().getRowIndex();
        while (lastRowIndex + 1 < rowIndex) {
            // 每次都会拿新的一行
            xlsxReadContext.readRowHolder(new ReadRowHolder(lastRowIndex + 1, RowTypeEnum.EMPTY,
                xlsxReadSheetHolder.getGlobalConfiguration(), new LinkedHashMap<Integer, Cell>()));
            // 调用invoke方法
            xlsxReadContext.analysisEventProcessor().endRow(xlsxReadContext);
            xlsxReadSheetHolder.setColumnIndex(null);
            xlsxReadSheetHolder.setCellMap(new LinkedHashMap<Integer, Cell>());
            lastRowIndex++;
        }
        xlsxReadSheetHolder.setRowIndex(rowIndex);
    }

@Override
public void endRow(AnalysisContext analysisContext) {
    if (RowTypeEnum.EMPTY.equals(analysisContext.readRowHolder().getRowType())) {
        if (LOGGER.isDebugEnabled()) {
            LOGGER.warn("Empty row!");
        }
        if (analysisContext.readWorkbookHolder().getIgnoreEmptyRow()) {
            return;
        }
    }
    dealData(analysisContext);
}
private void dealData(AnalysisContext analysisContext) {
    ReadRowHolder readRowHolder = analysisContext.readRowHolder();
    Map<Integer, ReadCellData<?>> cellDataMap = (Map)readRowHolder.getCellMap();
    readRowHolder.setCurrentRowAnalysisResult(cellDataMap);
    int rowIndex = readRowHolder.getRowIndex();
    int currentHeadRowNumber = analysisContext.readSheetHolder().getHeadRowNumber();

    boolean isData = rowIndex >= currentHeadRowNumber;

    // Last head column
    if (!isData && currentHeadRowNumber == rowIndex + 1) {
        buildHead(analysisContext, cellDataMap);
    }
    // Now is data
    for (ReadListener readListener : analysisContext.currentReadHolder().readListenerList()) {
        try {
            if (isData) {
                readListener.invoke(readRowHolder.getCurrentRowAnalysisResult(), analysisContext);
... ...
}

相关文章

  • POI和EasyExcel比较

    POI: 1.userModel模式一种是使用最多的,像用的HSSFWorkBook、XSSFWorkBook、S...

  • Java一行代码读写Excel

    SpringBoot整合EasyExcel Java解析、生成Excel比较有名的框架有Apache poi、jx...

  • alibaba/easyexcel 框架使用

    JAVA解析Excel工具easyexcel Java解析、生成Excel比较有名的框架有Apache poi、j...

  • SpringBoot整合EasyExcel进行报表导入导出

    引入 为什么使用EasyExcel? Java解析、生成Excel比较有名的框架有Apache poi、jxl。但...

  • 简单Excel使用

    什么是 easyexcel Java解析、生成Excel比较有名的框架有Apache poi、jxl。但他们都存在...

  • easyexcel中poi

    陈旧的项目导出excel时用的POI3.14,现在引入easyexcel2.2.6,报错。 easyexcel依赖...

  • POI、EasyExcel

    处理Excel框架介绍 apache POI xls是旧版Excel格式文件,xlsx是新版Excel格式文件;而...

  • POI and EasyExcel

    Excel 03版xls 最多65536行 07版xlsx 没有限制 POI apache HSSF -读写Mic...

  • 集成easyExcel

    引用easyExcel作者的一段话: Java解析、生成Excel比较有名的框架有Apache poi、jxl。但...

  • 代码简洁之道之easyexcel

    easyExcel是阿里巴巴开源poi插件之一,当前最新版本1.1.2-beta5,poi版本3.17,因此,集成...

网友评论

      本文标题:POI和EasyExcel比较

      本文链接:https://www.haomeiwen.com/subject/kosjurtx.html