当前位置: 首页 > article >正文

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

文章目录

    • 百万级 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 格式文件)。

结语

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


http://www.kler.cn/a/2943.html

相关文章:

  • 论文阅读:Realistic Noise Synthesis with Diffusion Models
  • flowable expression和json字符串中的双引号内容
  • OpenFeign的工作原理是什么?它第一次加载的时候为什么慢?
  • android 圆形弹窗摄像头开发踩坑——源码————未来之窗跨平台操作
  • 鸿蒙开发黑科技“stack叠层”替代customdialog
  • .NET MAUI进行UDP通信(二)
  • 【Linux】基于阻塞队列的生产者消费者模型
  • Qt音视频开发22-音频播放QAudioOutput
  • 【亲测搭建成功】模拟无网络情况下安装K8S集群和相关组件
  • 导航雷达回波信号格式和目标检测算法
  • 走进Vue【三】vue-router详解
  • java多线程之线程安全(重点,难点)
  • 什么是黄金现货市场
  • 【算法】前缀和
  • 解决win10任何程序打开链接仍然为老旧IE的顽固问题[修改默认浏览器]
  • 重构类关系-Pull Up Constructor Body构造函数本体上移三
  • 2023年通过CDGA的朋友可以考CDGP数据治理专家认证啦!
  • 传感器之相机介绍和使用
  • 游戏开发中常用的算法(持续更新)
  • 206. 反转链表
  • [数据结构]排序算法
  • Swift入门
  • 类和对象 - 下
  • 第二十一天 数据库开发-MySQL
  • 大文件上传
  • forward函数——浅学深度学习框架中的forward