POI和EasyExcel比較

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的這個方法,達到更小的內存占用。通過將流一行行的讀取,加載到內存,達到節(jié)約內存的目的。


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方法會去調用之初始化的監(jiān)聽器,執(zhí)行業(yè)務處理,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);
... ...
}

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容