我需要解决的情况:
我的客户有一些非常大的.xlsx文件,类似于数据库表(每行是一条记录,列是字段)
我需要帮助他们处理这些文件(搜索、过滤等)。
总的来说,我的意思是其中最小的有 100 万条记录。
我尝试过的:
System.OverflowException
,我的猜测是它基本上内存不足,因为一个200MB的xlsx文件已经占用了我4GB的内存阅读。由于保密,我无法共享实际文件,但您可以轻松创建具有 60 列(名字、姓氏、出生日期等)和大约 1M 记录的类似结构。
一旦您可以按照该条件读取 .xlsx 文件,删除一半记录,然后写入另一个位置,而不会遇到内存问题,问题就会得到解决。
时间并不是什么大问题。如果需要,用户愿意等待一两个小时以获得结果。
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);
}
}
}
:使用任何不将sharedStringTable.xml 文件加载到RAM 中的库。我见过很多库,但都将sharedStringTable加载到RAM中。所以我自己开发了一个。这里是源代码和NuGet包。
长答案:Xlsx 文件格式基本上是 zip 文件,其中包含 xml 文件形式的工作表。出于优化目的,Xlsx 文件将重复的单元格值存储在sharedString.xml 文件中,并引用重复单元格值的sharedString 条目的索引。大多数库将整个共享字符串加载到列表/字典中以进行查找,因此处理大型 Xlsx 文件会消耗大量 RAM。 XlsxHelper 采用了不同的方法。对于小文件,它将sharedString加载到RAM中,以便它可以非常快速地进行查找。对于较大的文件,它将 shareString 索引到文件中并执行 fileStream 读取,因此对于大文件,它占用的 RAM 非常少,但速度稍慢。