优化使用ClosedXML读取XLSX文件时的内存使用

问题描述 投票:0回答:3

我有一个 XLSX 工作表,其中包含大约 30 列和 130,000 行。

过去我使用OleDb数据读取器来解析此类文件,但在读取具有混合单元数据类型的未知Excel文件时会出现问题。

我找到了 ClosedXML,但我遇到的问题是内存使用量比 OleDb 高得多。我可能遗漏了一些东西,但似乎必须先加载整个工作簿,然后才能访问单个单元格,当我想读取单个单元格时,我的内存使用量会增加约 500MB:

        using (XLWorkbook workBook = new XLWorkbook(_path))
        {
            IXLWorksheet workSheet = workBook.Worksheet(tableName);
            Console.WriteLine(workSheet.Cell(1, 1).Value);
        }

有什么办法可以优化这个吗?

  • 惰性加载单元?
  • 仅将加载的单元格属性数量减少到感兴趣的单元格属性?
  • 有什么吗?

如果没有选项可以优化此功能,您能否推荐任何其他框架/库?

谢谢。

c# .net excel xlsx closedxml
3个回答
1
投票

内存使用可能很难避免,具体取决于文件中数据的类型。在内部,Excel 文件使用“共享字符串”表来存储每个字符串的单个副本,并通过工作表数据中的索引引用这些字符串。我想大多数库都会在读取任何工作表数据之前加载整个共享字符串表。如果您的文件有很多唯一的字符串,则可能需要一些时间和内存来加载整个共享字符串表。

ClosedXML 是读取 Excel 数据效率最低的库之一。正如 Francois 提到的,这可能并不奇怪,因为该库旨在支持其他库不支持的深度功能。

如果您想要的只是数据读取功能,您可以看一下我维护的库:Sylvan.Data.Excel。它非常易于使用,是最快的 .NET Excel 数据阅读器库。在这个特定的基准测试中,Sylvan 比 ClosedXML 快 10 倍以上,并且只占用很小一部分内存。


0
投票

看来必须先加载整个工作簿,然后才能访问单个单元格,

这是正确的。这是 ClosedXML 的设计行为。它意味着更高的内存使用率,以促进更强大的细胞操作。如果内存使用对您来说是个问题,我建议您查看不同的库,也许是 EPPlus。


0
投票

正如@MarkPflug 所提到的,Sost of 库将整个sharedString 加载到RAM 中。正因为如此,它可以占用大量内存。

如果sharedString的大小大于20MB,

XlsxHelper不会将sharedString加载到RAM中。由于这种实现,对于小型 Xlsx 文件来说速度很快,对于大文件来说内存效率很高。

这里是源代码Nuget

的链接

免责声明:我是XlsxHelper

的作者
© www.soinside.com 2019 - 2024. All rights reserved.