由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文件流来获取共享字符串列表的方法
完整的项目文件可以从这里获取https://github.com/Nick-PAN/PdkXlsxFileIO
关于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
相关文章推荐
- Java中使用POI读取大的Excel文件或者输入流时发生out of memory异常参考解决方案
- SharePoint下载大文件失败 异常信息: system.OutOfMemoryException
- 文件下载报错:引发类型为“System.OutOfMemoryException”的异常-.Net 内存溢出
- Java中使用POI读取大的Excel文件或者输入流时发生out of memory异常参考解决方案
- SQL SERVER 导入.sql文件 出现SYSTEM.OUTOFMEMORY EXCEPTION 异常解决办法
- 发布网站时出现"加载配置文件时出错: 引发类型为“System.OutOfMemoryException”的异常"
- SharePoint下载大文件失败 异常信息: system.OutOfMemoryException
- (WeakReference )弱引用解决OutOfMemoryException异常
- System.OutOfMemoryException 的异常
- System.OutOfMemoryException 的异常的错误解决方案
- System.OutOfMemoryException: 引发类型为“System.OutOfMemoryException”的异常
- “System.OutOfMemoryException”类型的异常在 mscorlib.dll 中发生,但未在用户代码中进行处理
- sqlserver,执行生成脚本时“引发类型为“System.OutOfMemoryException”的异常”(已解决)
- .net发生类型为 System.OutOfMemoryException 的异常解决办法
- java.lang.OutOfMemoryError: Java heap space读取文件时出现这个异常
- Exception -- java.lang.OutOfMemoryError: PermGen space” -- java内存溢出异常
- sqlserver,执行生成脚本时“引发类型为“System.OutOfMemoryException”的异常”
- IIS 异常 “System.OutOfMemoryException”、“存储空间不足,无法完成此操作。”
- 类型为“System.OutOfMemoryException”的异常
- 【转】ASP.NET中OutOfMemoryException异常的处理方案