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还是蛮强大的,会用了就好了。