百万级 Excel导入数据库 效率太低? 基于 SAX 的事件模型 导入,将会解决 效率问题

百万级 Excel导入效率太低? 基于 SAX 的事件模型 导入,将会解决 效率问题

如果使用传统的基于 POI 的读写方式,处理大量数据时确实效率较低,可以考虑使用基于 SAX 的事件模型进行读写。

基于 SAX 的事件模型,是一种流式的读写方式,可以直接读取 Excel 文件中的 XML 格式数据,并将其转换为对象模型,因此具有较高的性能和较小的内存占用。

基于 SAX 的事件模型是一种流式的读写方式,它可以直接读取 Excel 文件中的 XML 格式数据,并将其转换为对象模型。在处理大量数据时,该方式具有较高的性能和较小的内存占用。

SAX 是 Simple API for XML(简单 XML 应用程序接口)的缩写,它是一种基于事件的 XML 解析技术,通过注册一些回调函数(事件处理程序),可以实现对 XML 文件的解析。SAX 解析器读取 XML 文档,并发送事件(例如元素开始、元素结束等)给注册的事件处理程序,通过事件处理程序对 XML 文档进行处理。

实现思路:

在基于 SAX 的事件模型中,我们可以通过 XSSFReader 类获取 Excel 文件的输入流,并使用 XMLReader 类来解析 Excel 文件中的 XML 数据。具体步骤如下:

  1. 准备写入的输出流,例如输出到文件或内存中。

​ 2.创建 SAX 事件处理程序,通过实现不同的回调函数来处理不同的事件,例如开始解析 Workbook、解析 Cell 的值、结束解析 Workbook 等。

  1. 获取 Excel 文件输入流,使用 OPCPackage 和 XSSFReader 类来读取 Excel 文件中的 XML 数据。

  2. 获取 Workbook 中每个 Sheet 的 XML 输入流,并使用 XMLReader 类来解析 Excel 文件中的 XML 数据。

  3. 在 SAX 事件处理程序中处理不同的事件,例如开始解析 Workbook、解析 Cell 的值、结束解析 Workbook 等。

  4. 写入缓存的数据,例如每隔一定行数进行一次缓存写入。

需要注意的是,由于使用了 SAX 事件模型,需要自己实现解析事件处理程序。在处理复杂的 Excel 文件时,可能需要编写更为复杂的事件处理程序。同时,使用 SAX 事件模型可以有效减少内存占用,但需要较多的 I/O 操作,因此在处理小规模数据时可能不如基于 POI 的读写方式效率高。

代码示例:

以下是一个基于 SAX 的事件模型示例代码:

// 准备写入的输出流
OutputStream os = new BufferedOutputStream(new FileOutputStream(outputFile));
SXSSFWorkbook writer = new SXSSFWorkbook(new XSSFWorkbook(), 10000);
SXSSFSheet outSheet = writer.createSheet();

// 定义 SAX 事件处理程序
DefaultHandler handler = new DefaultHandler() {
    
    
    private boolean isRow = false;
    private int rowIndex = 0;
    private int colIndex = 0;
    private Row outRow = null;

    // 开始解析 Workbook
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
    
    
        if (qName.equals("row")) {
    
    
            isRow = true;
            rowIndex++;
            colIndex = 0;
            outRow = outSheet.createRow(rowIndex - 1);
        } else if (qName.equals("c")) {
    
    
            String colRef = attributes.getValue("r");
            colIndex = CellReference.convertColStringToIndex(colRef.replaceAll("\\d", ""));
        }
    }

    // 解析 Cell 的值
    public void characters(char[] ch, int start, int length) throws SAXException {
    
    
        if (isRow) {
    
    
            String cellValue = new String(ch, start, length);
            Cell cell = outRow.createCell(colIndex, CellType.STRING);
            cell.setCellValue(cellValue);
        }
    }

    // 结束解析 Workbook
    public void endElement(String uri, String localName, String qName) throws SAXException {
    
    
        if (qName.equals("row")) {
    
    
            isRow = false;

            // 每隔 10000 行进行一次缓存写入
            if (rowIndex % 10000 == 0) {
    
    
                ((SXSSFSheet) outSheet).flushRows();
            }
        }
    }
};

// 获取 Excel 文件输入流
InputStream is = new BufferedInputStream(new FileInputStream(inputFile));
OPCPackage pkg = OPCPackage.open(is);
XSSFReader reader = new XSSFReader(pkg);

// 获取 Workbook 中每个 Sheet 的 XML 输入流,并解析处理
XMLReader parser = XMLReaderFactory.createXMLReader();
parser.setContentHandler(handler);
Iterator<InputStream> sheets = reader.getSheetsData();
while (sheets.hasNext()) {
    
    
    InputStream sheetStream = sheets.next();
    InputSource sheetSource = new InputSource(sheetStream);
    parser.parse(sheetSource);
    sheetStream.close();
}

// 写入缓存的数据
writer.write(os);
os.flush();
os.close();
writer.dispose();


上述示例代码通过解析 Excel 文件中的 XML 数据,实现了基于 SAX 的事件模型读写操作。这种方式适用于处理大量数据,具有较高的性能和较小的内存占用。

需要注意的是,由于使用了 SAX 事件模型,需要自己实现解析事件处理程序。在处理复杂的 Excel 文件时,可能需要编写更为复杂的事件处理程序。

注意:

基于 SAX 的事件模型适用于读取基于 XML 格式的 Excel 文件,因此只能读取 XLSX 格式的文件,而不能读取旧版的 XLS 格式。这是因为 XLSX 文件是基于 XML 格式的文件,而 XLS 文件则采用了一种二进制格式,无法通过基于 SAX 的事件模型进行解析。如果需要读取 XLS 文件,可以使用基于 POI 的读写方式,例如 HSSF(适用于读写 XLS 格式文件)和 XSSF(适用于读写 XLSX 格式文件)。

结语

如果这篇文章对您有所帮助,或者有所启发的话,求一键三连:点赞、评论、收藏➕关注,您的支持是我坚持写作最大的动力。

猜你喜欢

转载自blog.csdn.net/qq_44866828/article/details/129746975