您的位置:首页 > 编程语言 > C#

由OutOfMemoryException异常到Excel的Xlsx文件读写

2017-07-12 13:22 393 查看
最近在一个项目中要用到对Excel的XLSX文件进行读写,本来直接使用第三方库NPOI来实现,在对小文件进行读写时也没遇到什么问题。但在每次读完一个小文件再读一个大文件时,就会在NPOI的XSSFWorkbook类型对象初始化中抛出System.OutOfMemoryException异常。在网上也查了相关资料,有说加内存的解决的,有说是托管代码的问题。也尝试使用EPPlus,也会出现同样的问题。采用Open-XML-SDK来解决,也有类似问题。最后,还是决定不使用第三方库,自己动手写一个XLSX文件读写库。

关于XLSX文件,通过搜索相关资料可以知道这是一种压缩格式。可以直接将XLSX文件解压缩,解压后的目录结构如下图1



继续打开xl文件夹,目录如下图2



这里就是我们主要关注的地方了。
workbook.xml文件主要关注里面的<sheets />节点,里面的子节点对应excel的每个sheet表格。通过<sheet />节点的name属性记录表格的名称。

sharedStrings.xml文件含有XLSX文件中单元格里用到的字符串。每个单元格字符串对应一个<si />节点,每个<si />节点里有至少一个<t />节点,每个<t />节点的内容就是单元格字符串的一部分。一般情况一个<si />节点下只有一个<t />节点,那么这个<t />节点的内容就是一个完整的单元格字符串;也可能出现多个<t />节点,那么就要把每个<t />节点的内容拼接起来,才形成一个单元格的字符串。
styles.xml文件记录了单元格的样式,一般不会对它进行处理。
worksheets文件夹内是Excel文件每张sheet表格对应的文件,文件名为sheet1.xml、sheet2.xml、sheet3.xml...如此类推。sheet1.xml代表第一张sheet表格的内容。重点关注<dimension />节点,她记录了网格的范围大小,如“A1”代表这张表只有一个单元格;如“A1:AA10”代表26×10大小的表格。<row />节点代表一行单元格,属性r代表从1开始的行编号。<c
/>节点代表某个单元格,属性r代表单元格位置,如r="A1"代表位于第1行A列,属性t表示单元格值的类型,如t="s"代表<v />节点的内容是共享字符串的索引。如果属性t没有,就表示<v />节点的内容就是单元格的值。
在读写过程中最容易出错的地方就是共享字符串的读取,如果读取不完整,就会导致解析不出正确的数据。下面是读取sharedStrings.xml文件流来获取共享字符串列表的方法

/// <summary>
/// 读取共享字符串表单
/// </summary>
/// <param name="input">sharedStrings.xml文件流</param>
/// <returns></returns>
private static IList<string> ReadStringTable(Stream input)
{
var stringTable = new List<string>();
using (var reader = XmlReader.Create(input))
{
string meta = "";
bool added = true;

for (reader.MoveToContent(); reader.Read(); )
{
if (reader.NodeType == XmlNodeType.Element)
{
if (reader.Name == "si")
{
if (!added)
{
stringTable.Add(meta);
added = true;
}
meta = "";
added = false;

}
if (reader.Name == "t")
{
meta += reader.ReadElementString();
}
}
else if (reader.NodeType == XmlNodeType.EndElement)
{
if (reader.Name == "si")
{
if (!added)
{
stringTable.Add(meta);
added = true;
}
}
else if (reader.Name == "sst")
{
if (!added)
{
stringTable.Add(meta);
added = true;
}
}
}
}
}

return stringTable;
}


完整的项目文件可以从这里获取https://github.com/Nick-PAN/PdkXlsxFileIO
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  excel XLSX C# .net
相关文章推荐