如何使用C#处理非常大的.xlsx文件

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

我需要解决的情况:

我的客户有一些非常大的.xlsx文件,类似于数据库表(每行是一条记录,列是字段)

我需要帮助他们处理这些文件(搜索、过滤等)。

总的来说,我的意思是其中最小的有 100 万条记录。


我尝试过的:

  • SheetJS 和 NPOI:两个库都只回复一个简单的“文件太大”。
  • EPPlus:可以读取几百K记录的文件,但是当面对实际文件时它只是给我一个
    System.OverflowException
    ,我的猜测是它基本上内存不足,因为一个200MB的xlsx文件已经占用了我4GB的内存阅读。
  • 我没有尝试过 Microsoft OleDB,但我宁愿避免它,因为我不想仅仅为了工作而购买 Microsoft Office。

由于保密,我无法共享实际文件,但您可以轻松创建具有 60 列(名字、姓氏、出生日期等)和大约 1M 记录的类似结构。

一旦您可以按照该条件读取 .xlsx 文件,删除一半记录,然后写入另一个位置,而不会遇到内存问题,问题就会得到解决。

时间并不是什么大问题。如果需要,用户愿意等待一两个小时以获得结果。
  • 目前内存似乎是问题。这是个人请求,客户的机器是一台内存上限为 8GB 的笔记本电脑。
  • csv
  • 不是
  • 这里的一个选项。我的客户有 .xlsx 输入并需要 .xlsx 输出。 语言选择最好是 JS、C# for Python,因为我已经知道如何用它们创建可执行文件(我们不能告诉会计师学习终端,不是吗?)。
  • 如果有一种方法可以慢慢地从文件中逐行读取小块数据,那就太好了,但我发现的解决方案只能同时读取整个文件。

c# excel memory-management
2个回答
7
投票
Excel

文件,我会推荐

ExcelDataReader
。它在读取大文件时表现非常好。我亲自尝试过500k-1M

using (var stream = File.Open("C:\\temp\\input.xlsx", FileMode.Open, FileAccess.Read)) { using (var reader = ExcelReaderFactory.CreateReader(stream)) { while (reader.Read()) { for (var i = 0; i < reader.FieldCount; i++) { var value = reader.GetValue(i)?.ToString(); } } } }

以同样有效的方式写回数据更加棘手。我最终创建了自己的 
SwiftExcel

库,该库非常快速且高效(有一个性能图表与其他 Nuget 库(包括

EPPlus
)进行比较),因为它不使用任何 XML 序列化并将数据直接写入文件:

using (var ew = new ExcelWriter("C:\\temp\\test.xlsx")) { for (var row = 1; row <= 100; row++) { for (var col = 1; col <= 10; col++) { ew.Write($"row:{row}-col:{col}", col, row); } } }



0
投票
简短回答

:使用任何不将sharedStringTable.xml 文件加载到RAM 中的库。我见过很多库,但都将sharedStringTable加载到RAM中。所以我自己开发了一个。这里是源代码NuGet包

长答案:

Xlsx 文件格式基本上是 zip 文件,其中包含 xml 文件形式的工作表。出于优化目的,Xlsx 文件将重复的单元格值存储在sharedString.xml 文件中,并引用重复单元格值的sharedString 条目的索引。大多数库将整个共享字符串加载到列表/字典中以进行查找,因此处理大型 Xlsx 文件会消耗大量 RAM。 XlsxHelper 采用了不同的方法。对于小文件,它将sharedString加载到RAM中,以便它可以非常快速地进行查找。对于较大的文件,它将 shareString 索引到文件中并执行 fileStream 读取,因此对于大文件,它占用的 RAM 非常少,但速度稍慢。

© www.soinside.com 2019 - 2024. All rights reserved.