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及 ...
随机推荐
- jenkins+stf+airtest实现移动端自动化测试平台
背景: 公司android测试机比较多没有统一的管理: app自动化测试时获取设备的状态比较麻烦,通过STF可以轻松获取: 自动化异常场景时.可远程操控设备: 需要随时了解设备情况: 装逼 前提: 已 ...
- docker 安装portainer容器后,启动/Portainer 安装MySQL并开启远程访问
启动命令: docker run -d -p 9000:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --nam ...
- 读后笔记 -- Java核心技术(第11版 卷 II) Chapter2 输入与输出
2.1 输入 / 输出流 No relationship with java.util.stream. 抽象类 Readers/writes process characters, not bytes ...
- django连接ubuntu22下的mysql8
1.安装mysql(这里就不过多赘述了) sudo apt-get install mysql-server 2.登录mysql (1) 在 根目录/etc/mysql/debian.cnf ,使 ...
- R语言广义线性模型(GLM)、全子集回归模型选择、检验分析全国风向气候数据|附代码数据
全文链接:http://tecdat.cn/?p=30914 最近我们被客户要求撰写关于广义线性模型(GLM)的研究报告,包括一些图形和统计输出. 我们正和一位朋友讨论如何在R软件中用GLM模型处理全 ...
- Linux 常用监控指标总结
1. Linux运维基础采集项 做运维,不怕出问题,怕的是出了问题,抓不到现场,两眼摸黑.所以,依靠强大的监控系统,收集尽可能多的指标,意义重大.但哪些指标才是有意义的呢,本着从实践中来的思想,各位工 ...
- Git克隆项目到本地
刚进公司实习,居然不知道Git怎么克隆项目到本地,组长丢给我一个TFS账号(Azure DevOps就是以前的TFS) 1.首先在本地选择一个文件目录,选择Git Bash Here 打开一个Git ...
- Vue 局部过滤器和全局过滤器
Vue 过滤器总结: 定义:对要显示的数据进行特定格式化后再显示(适用于一些简单逻辑的处理) 语法: 1.注册过滤器: Vue.filter(name,callback) 或 new Vue{filt ...
- PyMySQL创建
title: PyMySQL创建 author: 杨晓东 permalink: PyMySQL创建 date: 2021-10-02 11:27:04 categories: - 投篮 tags: - ...
- C语言中return和exit的区别
转载自:http://jszx.cuit.edu.cn/NewsCont.asp?bm=00&type=888&id=20050 1.exit用于在程序运行的过程中随时结束.终止程序, ...