当前位置: 代码迷 >> 综合 >> 记一次java使用POI读取Excel-xlsx
  详细解决方案

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

热度:18   发布时间:2023-11-16 23:59:00.0

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,通过自定义解析器去读取。

读取后注意类型的转换

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);// 获得第一个sheetInputStream 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;}//元素开始时的handlerpublic 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 = "";}//元素结束时的handlerpublic 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);}}//读取元素间内容时的handlerpublic 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类型。

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的错误了。删去就行了。

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

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

  相关解决方案