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及 ...
随机推荐
- 遇到端口占用无法启动IIS Express服务器
报错图片: 上图所述由于端口被占用无法完成IIS Express的输出 这时候要考虑到自己在Windows的IIS 是不是配置了该端口? 很明显,就是配置了一个8091的端口且还在启动中,这时候要先将 ...
- 大小写字符转换【Sql Server和C#两种写法】
案例:Var Str = "abdCnd" 如何将Str = "ABDCND"? Sql Server写法:upper(Str) ==> Lower ...
- 阿里云centos7安装图形界面gnome
这应该是很无聊很蛇精的操作吧. 首先命令行远程登陆阿里云,然后root身份更新系统,安装gnome这些操作(菜如我以前都没有操作过),参照网上虚拟机的教程. # yum update -y # yum ...
- C2驾驶车型
凡是自动挡的9座(包括9座)以下,车长6米以内的小型载客汽车(包含轿车.SUV.MPV):以及总质量在4500KG(包括4500KG)以下的.车长在6米(包括6米)以下的.核定载重质量在1500KG( ...
- Burpsuite入门之target模块攻防中利用
可以用来收集目标站点的更多资产 可以探测一些自动加载的接口.内容等,有的内容并不能被访问者直接看见,通过抓包的方式就可以一目了然. 1栏中是流量信息,其中包含着你所请求的流量 2栏中是对1栏中内容的一 ...
- 手机安装APK文件,出现-应用未安装-软件包无效-安装包异常
在项目的根的gradle.properties文件中添加 android.injected.testOnly=false 即可. 猜想:因为是在打debug包,然后这个属性变为了true?然后手机会因 ...
- STP协议-基础
生成树协议 一 .技术背景一个缺乏冗余性设计的网络:任何一个网络节点出现故障,会造成单链路故障.单设备故障,使整个网络瘫痪. 引入冗余性的同时也引入了二层环路:网络的冗余性增强了,但是却出现了二层环路 ...
- Uri转绝对路径工具类
/** * 反射从 provider uri中获取 文件绝对路径 * @param context * @param uri * @return */ private static String ge ...
- mysql掉电后重启失败问题
报错 2022-12-07T01:41:02.844533Z 0 [ERROR] InnoDB: Ignoring the redo log due to missing MLOG_CHECKPOIN ...
- @JsonSerialize(using = ToStringSerializer.class) 转换失败
解决方案 但实际开发过程中,数据库的bigint,Java的Long都是比较常用的数据类型,为了避免精度丢失,针对这种比较大的数值 全局配置,将数值类型转换为文本如果需要将所有的数值类型全部转换成文本 ...