poi解析Excel2007海量数据
处理excel,开源的javaApI提供了两种,一种是jxl,一种是poi。poi提供的功能较多,所以我用的是poi。
poi有两种模式,一个是用户模式(HSSFworkbook:支持Excel2003,XSSFworkbook:支持Excel2007),这个操作数量上万的时候会造成out of memory 的情况。另一个是事件驱动模,解析的Excel数据上万的时候用这个,这里拿Excel2007来说明,Excel2007的底层其实就是xml形式的,其实也就是解析xml。
底层xml格式:
<sheetData>//代表一个shet
- <row r="1" spans="1:33">//代表一个行
- <c r="A1" t="s">//代表一个单元格 r是坐标
<v>0</v> //代表相应的值,这里的0不是真正的值
</c>
- <c r="B1" t="s">
<v>1</v>
</c>
- <c r="C1" t="s">
<v>2</v>
</c>
</row>
</sheetData>
所需jar包:poi.jar,poi-excelant,poi-ooxml.jar,poi-ooxml-schemas.jar,poi- scratchpad.jar,dom4j.jar,xmlbeans.jar,xerces.jar
代码:空值问题待解决
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xssf.eventusermodel.ReadOnlySharedStringsTable;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.model.StylesTable;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory; //Default是sax解析xml的处理类
public class TestExcel2007Util{
public static void main(String[] args) throws IOException, OpenXML4JException, SAXException {
Excel2007Util excel2007Util=new Excel2007Util();
excel2007Util.process("C:/Users/sime/Desktop/XXX.xlsx"); }
}
class Excel2007Util extends DefaultHandler{
//共享字符串表
private ReadOnlySharedStringsTable sst;
//单元格
private StylesTable stylesTable; private String lastContents; private boolean nextIsString; private List<String> rowlist=new ArrayList<String>();
//当前页
private int sheetIndex;
//当前行
private int curRow =0;
//当前单元格
private int curCol =0;
private boolean cellNull; /**
* excel记录行操作方法,rowlist是一行记录,这里可以进行你的逻辑处理
*/
public void optRows(int sheetIndex,int curRow,List<String> rowlist){
System.out.println(rowlist.toString());
} /**
* 遍历工作簿中所有的电子表格
* @throws OpenXML4JException
* @throws IOException
* @throws SAXException
*/
public void process (String filename) throws IOException, OpenXML4JException, SAXException{
OPCPackage pkg = OPCPackage.open(filename);
XSSFReader xssfReader = new XSSFReader(pkg);
sst = new ReadOnlySharedStringsTable(pkg);
XMLReader parser=this.fetchSheetParser(sst);
Iterator<InputStream> sheets = xssfReader.getSheetsData();
while (sheets.hasNext()) {
curRow = 0;
sheetIndex++;
InputStream sheet = sheets.next();
InputSource sheetSource = new InputSource(sheet);
parser.parse(sheetSource);
sheet.close();
}
pkg.close();
}
public XMLReader fetchSheetParser(ReadOnlySharedStringsTable sst) throws SAXException {
XMLReader parser = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");
parser.setContentHandler(this);
return parser;
} /**
* 解析器在 XML 文档中的每个元素的开始调用此方法
* uri:名称空间 URI
* localName:本地名称
* name:限定名
* attributes:连接到元素上的属性
*/
public void startElement(String uri, String localName, String name, Attributes attributes){
if (name.equals("c")) {
// 如果下一个元素是 SST 的索引,则将nextIsString标记为true
String cellType = attributes.getValue("t");
// System.out.println("cellType : " + cellType);
if (cellType != null && cellType.equals("s")) {
nextIsString = true;
cellNull = false;
} else {
nextIsString = false;
cellNull = true;
}
}
lastContents = "";
}
// 根据SST的索引值的到单元格的真正要存储的字符串
// 这时characters()方法可能会被调用多次
public void characters(char[] ch, int start, int length) throws SAXException {
//得到单元格内容的值
lastContents += new String(ch, start, length); } public void endElement (String uri, String localName, String name){
if (nextIsString) {
try {
int idx = Integer.parseInt(lastContents);
lastContents = new XSSFRichTextString(sst.getEntryAt(idx)).toString();
} catch (Exception e) { }
} // v => 单元格的值,如果单元格是字符串则v标签的值为该字符串在SST中的索引
// 将单元格内容加入rowlist中,在这之前先去掉字符串前后的空白符
if (name.equals("v") || "t".equals(name)) {
String value = lastContents.trim();
rowlist.add(curCol, value);
curCol++;
cellNull = false;
}else if("c".equals(name)){
rowlist.add(curCol, "");
curCol++;
cellNull = false;
}else {
//如果标签名称为 row ,这说明已到行尾,调用 optRows() 方法
if (name.equals("row")) {
optRows(sheetIndex,curRow,rowlist);
rowlist.clear();
curRow++;
curCol = 0;
}
}
} }
这是个人网上百度后总结的方法,比较简洁,可以直接拿去用,但是空值的问题尚未解决,如有不对的地方请指出。
org.apache.xerces.parsers.SAXParser
poi解析Excel2007海量数据的更多相关文章
- POI Sax 事件驱动解析Excel2007文件
Excel2007版本的代码如下,本文主要是用于POI解析大文件Excel容易出现内存溢出的现象而提出解决方案,故此解决了大数据量的Excel文件解析的难度,在此拿出来贡献给大家,谢谢! 里面用到的相 ...
- POI以SAX方式解析Excel2007大文件(包含空单元格的处理) Java生成CSV文件实例详解
http://blog.csdn.net/l081307114/article/details/46009015 http://www.cnblogs.com/dreammyle/p/5458280. ...
- java 使用 poi 解析excel
背景: web应用经常需要上传文件,有时候需要解析出excel中的数据,如果excel的格式没有问题,那就可以直接解析数据入库. 工具选择: 目前jxl和poi可以解析excel,jxl很早就停止维护 ...
- poi解析excel
一.遇见的问题: 当单元格设置为日期类型时,cell.getCellStyle().getDataFormat()返回的值都为176. poi jar包3.14以上不支持用cell.getCellTy ...
- poi解析Excel文件版本问题
poi解析Excel文件时有两种格式: HSSFWorkbook格式用来解析Excel2003(xls)的文件 XSSFWorkbook格式用来解析Excel2007(xlsx)的文件 如果用HSSF ...
- SpringMVC文件上传 Excle文件 Poi解析 验证 去重 并批量导入 MYSQL数据库
SpringMVC文件上传 Excle文件 Poi解析并批量导入 MYSQL数据库 /** * 业务需求说明: * 1 批量导入成员 并且 自主创建账号 * 2 校验数据格式 且 重复导入提示 已被 ...
- Apache POI解析excel文件
这里需要用到poi.jar和poi-ooxml.jar 没有的可以去http://mvnrepository.com/下载 import org.apache.poi.POIXMLDocument; ...
- java读写excel文件( POI解析Excel)
package com.zhx.base.utils; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi ...
- 使用POI解析Excel时,出现org.xml.sax.SAXParseException: duplicate attribute 'o:relid'的解决办法
1.使用org.apache.poi解析excle,.xlsx类型文件InputStream is = new FileInputStream(strFileName);XSSFWorkbook wb ...
- poi解析excel出现格式不正确
后缀为xlsx的excel做系统导入时出现bug: Strict OOXML isn't currently supported, please see bug #57699 为了同时兼容03.07及 ...
随机推荐
- VMware VirtualCenter Servere服务不能启动
故障现象现象:VMware VirtualCenter Servere服务不能启动 解决办法:进入%programdata%\VMware\VMwareVirtualCenter\Logs目录下面. ...
- 浅谈Redis与分布式锁
为什么需要分布式锁 Redis如何实现分布式锁 如何避免死锁? 锁被别人释放怎么办? 锁过期时间不好评估怎么办? Redlock 真的安全吗 为什么要在多个实例上加锁? 为什么大多数实例加锁成功,才算 ...
- 建筑CAD中如何标注动态标高?CAD标注动态标高步骤
在建筑CAD软件中,标高标注用来表示某个点的高程或者垂直高度.浩辰CAD建筑软件中以标高对象来实现CAD标高的标注,标高画法符合国家建筑制图统一标准与总图制图标准的图例,同时也提供了流行的楼层标高画法 ...
- 【TensorFlow】Tensorflow-GPU 环境搭建教程(附 Windows 版本对应表及 CUDA GPU 计算能力表)
conda教程(推荐):『Tensorflow GPU Installation Made Easy: Use conda instead of pip [Update-2] | by Harveen ...
- 记一个在线工具网站,程序员必备,json格式化、压缩、转义,加解密 编码解码
简用-在线工具箱-简单易用-工具大全 提供 json格式化,json代码压缩,json校验解析,json数组解析,json转xml,xml转json,json解析,json在线解析,json在线解析及 ...
- CentOS7 minimal 安装 VMware Tools(自带脚本安装)
1.安装相关组件 yum -y install perl gcc make kernel-headers kernel-devel net-tools 2.新建挂载目录 mkdir -p /mnt/c ...
- Filter Pattern 2 (dubbo的实现方式)
前一篇FilterPattern的范式,基本和Tomcat实现的filter chain是一样的: 这里介绍一下我看完dubbo关于Filter Pattern的实现思路,自己抽象出来的代码,以及理解 ...
- Reactor 模式线程模型
根据Reactor的数据量和处理资源池线程数量,可以分为3钟典型实现 单Reactor单线程 单Reactor 多线程 主从Reactor 多线程
- C语言学习---星花与取地址&----以及多级指针
#include<stdio.h> int main { //对一个表达式加* , 就会对表达式减一级星花*, //如果对表达式取&, 就会加一级* int* p; int** q ...
- MySQL查询时记录行号rownum MySQL查询显示行号MySQL查询显示行号MySQL流水号自MySQL自增行号
MySQL查询时记录行号rownum MySQL查询显示行号MySQL查询显示行号MySQL流水号自MySQL自增行号 一.前言 Oracle中有rownum,实现查询的时候记录行号,MySQL中没有 ...