欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

JAVA解析Excel工具easyexcel之深入源代码解密原理

程序员文章站 2024-01-08 13:06:16
...
    EasyExcel.read(file, HeadReadData.class, new HDListener()).sheet(0).doRead();

EasyExcel.read(file, HeadReadData.class, new HDListener())将文件、表头类、读监听器传进去,创建ExcelReaderBuilder并将三个参数保存到ExcelReaderBuilder中的一个属性ReadWorkbook中。

public static ExcelReaderBuilder read(File file, Class head, ReadListener readListener) {
        //创建excel读构建器
        ExcelReaderBuilder excelReaderBuilder = new ExcelReaderBuilder();
        //分别传入file、head、readListener
        excelReaderBuilder.file(file);
        if (head != null) {
            excelReaderBuilder.head(head);
        }
        if (readListener != null) {
            excelReaderBuilder.registerReadListener(readListener);
        }
        return excelReaderBuilder;
    }
public class ExcelReaderBuilder {
    /**
     * Workbook
     */
    private ReadWorkbook readWorkbook;

    public ExcelReaderBuilder() {
        this.readWorkbook = new ReadWorkbook();
    }
    
ReadWorkbook extends ReadBasicParameter

EasyExcel.read(file, HeadReadData.class, new HDListener()).sheet(0).doRead();

 public ExcelReaderSheetBuilder sheet(Integer sheetNo) {
        return sheet(sheetNo, null);
    }

sheet(0)返回 excelReaderSheetBuilder构建器

 public ExcelReaderSheetBuilder sheet(Integer sheetNo, String sheetName) {
        ExcelReaderSheetBuilder excelReaderSheetBuilder = new ExcelReaderSheetBuilder(build());
        if (sheetNo != null) {
            excelReaderSheetBuilder.sheetNo(sheetNo);
        }
        if (sheetName != null) {
            excelReaderSheetBuilder.sheetName(sheetName);
        }
        return excelReaderSheetBuilder;
    }

而build()就是利用文件、表头类、读监听器返回一个ExcelReader,readWorkbook中保存了文件、表头类、读监听器。

public ExcelReader build() {
        return new ExcelReader(readWorkbook);
    }

ExcelReader

  public ExcelReader(ReadWorkbook readWorkbook) {
        excelAnalyser = new ExcelAnalyserImpl(readWorkbook);
    }

ExcelAnalyserImpl

 public ExcelAnalyserImpl(ReadWorkbook readWorkbook) {
        try {
            analysisContext = new AnalysisContextImpl(readWorkbook);
            choiceExcelExecutor();
        } catch (RuntimeException e) {
            finish();
            throw e;
        } catch (Throwable e) {
            finish();
            throw new ExcelAnalysisException(e);
        }
    }
    //选择不同的excel执行器,XLS、XLSX
    private void choiceExcelExecutor() throws Exception {
        ReadWorkbookHolder readWorkbookHolder = analysisContext.readWorkbookHolder();
        ExcelTypeEnum excelType = readWorkbookHolder.getExcelType();
        if (excelType == null) {
            excelReadExecutor = new XlsxSaxAnalyser(analysisContext, null);
            return;
        }
        switch (excelType) {
            case XLS:
            **//POIFSFileSystem poi的文件读取api
                POIFSFileSystem poifsFileSystem;**
                if (readWorkbookHolder.getFile() != null) {
                    poifsFileSystem = new POIFSFileSystem(readWorkbookHolder.getFile());
                } else {
                    poifsFileSystem = new POIFSFileSystem(readWorkbookHolder.getInputStream());
                }
                // So in encrypted excel, it looks like XLS but it's actually XLSX
                if (poifsFileSystem.getRoot().hasEntry(Decryptor.DEFAULT_POIFS_ENTRY)) {
                    InputStream decryptedStream = null;
                    try {
                        decryptedStream =
                            DocumentFactoryHelper.getDecryptedStream(poifsFileSystem.getRoot().getFileSystem(),
                                analysisContext.readWorkbookHolder().getPassword());
                        excelReadExecutor = new XlsxSaxAnalyser(analysisContext, decryptedStream);
                        return;
                    } finally {
                        IOUtils.closeQuietly(decryptedStream);
                        // as we processed the full stream already, we can close the filesystem here
                        // otherwise file handles are leaked
                        poifsFileSystem.close();
                    }
                }
                if (analysisContext.readWorkbookHolder().getPassword() != null) {
                    Biff8EncryptionKey.setCurrentUserPassword(analysisContext.readWorkbookHolder().getPassword());
                }
                excelReadExecutor = new XlsSaxAnalyser(analysisContext, poifsFileSystem);
                break;
            case XLSX:
                excelReadExecutor = new XlsxSaxAnalyser(analysisContext, null);
                break;
            default:
        }
    }

AnalysisContextImpl

    public AnalysisContextImpl(ReadWorkbook readWorkbook) {
        if (readWorkbook == null) {
            throw new IllegalArgumentException("Workbook argument cannot be null");
        }
        readWorkbookHolder = new ReadWorkbookHolder(readWorkbook);
        currentReadHolder = readWorkbookHolder;
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("Initialization 'AnalysisContextImpl' complete");
        }
    }

ReadWorkbookHolder开始读取readWorkbook中传进来的属性。

public ReadWorkbookHolder(ReadWorkbook readWorkbook) {
        super(readWorkbook, null, readWorkbook.getConvertAllFiled());
        this.readWorkbook = readWorkbook;
        if (readWorkbook.getInputStream() != null) {
            if (readWorkbook.getInputStream().markSupported()) {
                this.inputStream = readWorkbook.getInputStream();
            } else {
                this.inputStream = new BufferedInputStream(readWorkbook.getInputStream());
            }
        }
        this.file = readWorkbook.getFile();
        if (file == null && inputStream == null) {
            throw new ExcelAnalysisException("File and inputStream must be a non-null.");
        }
        if (readWorkbook.getMandatoryUseInputStream() == null) {
            this.mandatoryUseInputStream = Boolean.FALSE;
        } else {
            this.mandatoryUseInputStream = readWorkbook.getMandatoryUseInputStream();
        }
        if (readWorkbook.getAutoCloseStream() == null) {
            this.autoCloseStream = Boolean.TRUE;
        } else {
            this.autoCloseStream = readWorkbook.getAutoCloseStream();
        }

        // The type of excel is read according to the judgment.Because encrypted XLSX needs to be specified as XLS to
        // properly parse.
        this.excelType = ExcelTypeEnum.valueOf(file, inputStream, readWorkbook.getExcelType());

        if (ExcelTypeEnum.XLS == excelType && getGlobalConfiguration().getUse1904windowing() == null) {
            getGlobalConfiguration().setUse1904windowing(Boolean.FALSE);
        }
        this.customObject = readWorkbook.getCustomObject();
        if (readWorkbook.getIgnoreEmptyRow() == null) {
            this.ignoreEmptyRow = Boolean.TRUE;
        } else {
            this.ignoreEmptyRow = readWorkbook.getIgnoreEmptyRow();
        }
        if (readWorkbook.getReadCache() != null) {
            if (readWorkbook.getReadCacheSelector() != null) {
                throw new ExcelAnalysisException("'readCache' and 'readCacheSelector' only one choice.");
            }
            this.readCacheSelector = new EternalReadCacheSelector(readWorkbook.getReadCache());
        } else {
            if (readWorkbook.getReadCacheSelector() == null) {
                this.readCacheSelector = new SimpleReadCacheSelector();
            } else {
                this.readCacheSelector = readWorkbook.getReadCacheSelector();
            }
        }
        if (readWorkbook.getDefaultReturnMap() == null) {
            this.defaultReturnMap = Boolean.TRUE;
        } else {
            this.defaultReturnMap = readWorkbook.getDefaultReturnMap();
        }
        this.xlsxSAXParserFactoryName = readWorkbook.getXlsxSAXParserFactoryName();
        this.hasReadSheet = new HashSet<Integer>();
        this.ignoreRecord03 = Boolean.FALSE;
        this.password = readWorkbook.getPassword();
    }

以上便是初始化创建环境,下面开始读取文档内容:

EasyExcel.read(file, HeadReadData.class, new HDListener()).sheet(0)**.doRead();**
   public void doRead() {
        if (excelReader == null) {
            throw new ExcelGenerateException("Must use 'EasyExcelFactory.read().sheet()' to call this method");
        }
        excelReader.read(build());
        excelReader.finish();
    }
    public ReadSheet build() {
    //在前面环境构建的时候设置了readSheet对象,关于sheet的序号,名称
        return readSheet;
    }

调用excelReader的read

  public ExcelReader read(ReadSheet... readSheet) {
        return read(Arrays.asList(readSheet));
    }
 public ExcelReader read(List<ReadSheet> readSheetList) {
        excelAnalyser.analysis(readSheetList, Boolean.FALSE);
        return this;
    }

核心读取步骤:

  @Override
    public void analysis(List<ReadSheet> readSheetList, Boolean readAll) {
        try {
            if (!readAll && CollectionUtils.isEmpty(readSheetList)) {
                throw new IllegalArgumentException("Specify at least one read sheet.");
            }
            try {
            //根据创建环境时选择的excelReadExecutor进行读取
                excelReadExecutor.execute(readSheetList, readAll);
            } catch (ExcelAnalysisStopException e) {
                if (LOGGER.isDebugEnabled()) {
                    LOGGER.debug("Custom stop!");
                }
            }
            // The last sheet is read
            if (excelReadExecutor instanceof XlsSaxAnalyser) {
                if (analysisContext.readSheetHolder() != null) {
                    analysisContext.readSheetHolder().notifyAfterAllAnalysed(analysisContext);
                }
            }
        } catch (RuntimeException e) {
            finish();
            throw e;
        } catch (Throwable e) {
            finish();
            throw new ExcelAnalysisException(e);
        }
    }

两个excelReadExecutor
JAVA解析Excel工具easyexcel之深入源代码解密原理

 @Override
    public void execute(List<ReadSheet> readSheetList, Boolean readAll) {
        for (ReadSheet readSheet : sheetList) {
            readSheet = SheetUtils.match(readSheet, readSheetList, readAll,
                analysisContext.readWorkbookHolder().getGlobalConfiguration());
            if (readSheet != null) {
                analysisContext.currentSheet(readSheet);
                parseXmlSource(sheetMap.get(readSheet.getSheetNo()), new XlsxRowHandler(analysisContext, stylesTable));
                // The last sheet is read
                analysisContext.readSheetHolder().notifyAfterAllAnalysed(analysisContext);
            }
        }
    }
private void parseXmlSource(InputStream inputStream, ContentHandler handler) {
        InputSource inputSource = new InputSource(inputStream);
        try {
            SAXParserFactory saxFactory;
            String xlsxSAXParserFactoryName = analysisContext.readWorkbookHolder().getXlsxSAXParserFactoryName();
            if (StringUtils.isEmpty(xlsxSAXParserFactoryName)) {
                saxFactory = SAXParserFactory.newInstance();
            } else {
                saxFactory = SAXParserFactory.newInstance(xlsxSAXParserFactoryName, null);
            }
            saxFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
            saxFactory.setFeature("http://xml.org/sax/features/external-general-entities", false);
            saxFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
            SAXParser saxParser = saxFactory.newSAXParser();
            XMLReader xmlReader = saxParser.getXMLReader();
            xmlReader.setContentHandler(handler);
            xmlReader.parse(inputSource);
            inputStream.close();
        } catch (ExcelAnalysisException e) {
            throw e;
        } catch (Exception e) {
            throw new ExcelAnalysisException(e);
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    throw new ExcelAnalysisException("Can not close 'inputStream'!");
                }
            }
        }

监听器的调用:

 public void notifyEndOneRow(AnalysisFinishEvent event, AnalysisContext analysisContext) {
        Map<Integer, CellData> cellDataMap = event.getAnalysisResult();
        if (CollectionUtils.isEmpty(cellDataMap)) {
            if (LOGGER.isDebugEnabled()) {
                LOGGER.warn("Empty row!");
            }
            if (analysisContext.readWorkbookHolder().getIgnoreEmptyRow()) {
                return;
            }
        }
        ReadRowHolder readRowHolder = analysisContext.readRowHolder();
        readRowHolder.setCurrentRowAnalysisResult(cellDataMap);
        int rowIndex = readRowHolder.getRowIndex();
        int currentheadRowNumber = analysisContext.readSheetHolder().getHeadRowNumber();

        if (rowIndex >= currentheadRowNumber) {
            // Now is data
            for (ReadListener readListener : analysisContext.currentReadHolder().readListenerList()) {
                try {
                    **readListener.invoke(readRowHolder.getCurrentRowAnalysisResult(), analysisContext);**
                } catch (Exception e) {
                    for (ReadListener readListenerException : analysisContext.currentReadHolder().readListenerList()) {
                        try {
                            readListenerException.onException(e, analysisContext);
                        } catch (Exception exception) {
                            throw new ExcelAnalysisException(exception.getMessage(), exception);
                        }
                    }
                    break;
                }
                if (!readListener.hasNext(analysisContext)) {
                    throw new ExcelAnalysisStopException();
                }
            }
        } else {
            // Last head column
            if (currentheadRowNumber == rowIndex + 1) {
                buildHead(analysisContext, cellDataMap);
            }
            // Now is header
            for (ReadListener readListener : analysisContext.currentReadHolder().readListenerList()) {
                try {
                    readListener.invokeHead(cellDataMap, analysisContext);
                } catch (Exception e) {
                    for (ReadListener readListenerException : analysisContext.currentReadHolder().readListenerList()) {
                        try {
                            readListenerException.onException(e, analysisContext);
                        } catch (Exception exception) {
                            throw new ExcelAnalysisException(exception.getMessage(), exception);
                        }
                    }
                    break;
                }
                if (!readListener.hasNext(analysisContext)) {
                    throw new ExcelAnalysisStopException();
                }
            }
        }
    }
相关标签: easyexcel

上一篇:

下一篇: