您的位置:首页 > 编程语言 > Java开发

记一次java使用POI读取Excel-xlsx

2018-09-08 01:58 1881 查看
版权声明:版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_37465368/article/details/82470514

1、Excel分类:xls格式,xlsx格式,(Strict xlsx格式这次也接触到了)

2、两种类型的文件有两种不同的方式去读,另外也要注意文件创建的Excel版本

xls:HSSFReader

xlsx:XSSFReader

3、需求:将定量数据导入到mysql中

要求:使用poi去读取strict Excel格式的文件(xlsx),为了安全起见,觉得有种可行性,所以采取这种方式

尝试过后,一是不知道数据类型难以处理,二是网上很少有资料可供查询,最后实在读取不了,改为了读普通的xlsx

4、读取还是有两种方式可以采取

(1)数据量很小时,直接读就行了。

https://www.cnblogs.com/muliu/p/6812347.html

(2)数据量很大时,超过65535(16位)时,会造成内存泄露。

          采用流式读取,其实Excel2007版的xlsx底层采用的是xml,故将xlsx转为xml,读取xml,通过自定义解析器去读取。

读取后注意类型的转换

[code]public class ExampleEventUserModel{
public void processOneSheet(String filename) throws Exception {
OPCPackage pkg = OPCPackage.open(filename);
XSSFReader r = new XSSFReader( pkg );
SharedStringsTable sst = r.getSharedStringsTable();

XMLReader parser = fetchSheetParser(sst);

// 获得第一个sheet
InputStream sheet2 = r.getSheet("rId1");
InputSource sheetSource = new InputSource(sheet2);
parser.parse(sheetSource);
sheet2.close();
}

public XMLReader fetchSheetParser(SharedStringsTable sst) throws SAXException {
XMLReader parser =
XMLReaderFactory.createXMLReader(
"org.apache.xerces.parsers.SAXParser"
);
ContentHandler handler = new SheetHandler(sst);
parser.setContentHandler(handler);
return parser;
}

/**
* 处理sax的handler
*/
private static class SheetHandler extends DefaultHandler {
private SharedStringsTable sst;
private String lastContents;
private boolean nextIsString;

private SheetHandler(SharedStringsTable sst) {
this.sst = sst;
}

//元素开始时的handler
public void startElement(String uri, String localName, String name,
Attributes attributes) throws SAXException {
// c => 单元格
if(name.equals("c")) {
System.out.print(attributes.getValue("r") + " - ");
// 获取单元格类型
String cellType = attributes.getValue("t");
if(cellType != null && cellType.equals("s")) {
nextIsString = true;
} else {
nextIsString = false;
}
}
lastContents = "";
}

//元素结束时的handler
public void endElement(String uri, String localName, String name)
throws SAXException {
if(nextIsString) {
int idx = Integer.parseInt(lastContents);
lastContents = new XSSFRichTextString(sst.getEntryAt(idx)).toString();
nextIsString = false;
}

// v => 单元格内容
if(name.equals("v")) {
System.out.println(lastContents);
}
}

//读取元素间内容时的handler
public void characters(char[] ch, int start, int length)
throws SAXException {
lastContents += new String(ch, start, length);
}
}

public static void main(String[] args) throws Exception {
ExampleEventUserModel example = new ExampleEventUserModel();
example.processOneSheet("d://large.xlsx");
}

}

5、其他问题

(1)时间戳类型的转换,excel中存的是long串

         解决方案:java类Timestamp 转换之后可以直接存到数据库里,对应datetime类型。

[code]Long createTime = Long.valueOf(rowlist.get(i));
Timestamp timestamp = new Timestamp(createTime);

时间戳类型大小比较

timestamp.before(timestamp2)

timestamp.after(timestamp2)

 

(2)存到数据库遇到障碍:在静态类中无法调用dao层数据库语句

解决:将读到的数据,存到Entity中,然后存到List链中,然后返回出去,第一次体会到List的强大,40万条大概占用内存400M

粗暴了一点,哈哈哈哈

(3)依赖包问题:有些依赖包不支持XSSF方式读取文件

最后用的3.15-beta2....引入这一个依赖就ok,就包含了poi,poi-ooxml-schemas

开始都引入了,反而报缺少schemas的错误了。删去就行了。

[code]<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.15-beta2</version>
</dependency>

6、碰完错才发现poi还是蛮强大的,会用了就好了。

阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: