POI读取excel大量数据

首先,给个原文地址:http://thinkgem.iteye.com/blog/2150940

  1. import java.io.InputStream;  
  2. import java.math.BigDecimal;  
  3. import java.text.SimpleDateFormat;  
  4. import java.util.ArrayList;  
  5. import java.util.Date;  
  6. import java.util.Iterator;  
  7. import java.util.List;  
  8.   
  9. import org.apache.poi.hssf.usermodel.HSSFDateUtil;  
  10. import org.apache.poi.openxml4j.opc.OPCPackage;  
  11. import org.apache.poi.xssf.eventusermodel.XSSFReader;  
  12. import org.apache.poi.xssf.model.SharedStringsTable;  
  13. import org.apache.poi.xssf.usermodel.XSSFRichTextString;  
  14. import org.xml.sax.Attributes;  
  15. import org.xml.sax.InputSource;  
  16. import org.xml.sax.SAXException;  
  17. import org.xml.sax.XMLReader;  
  18. import org.xml.sax.helpers.DefaultHandler;  
  19. import org.xml.sax.helpers.XMLReaderFactory;  
  20.   
  21. /** 
  22.  * Excel超大数据读取,抽象Excel2007读取器,excel2007的底层数据结构是xml文件,采用SAX的事件驱动的方法解析 
  23.  * xml,需要继承DefaultHandler,在遇到文件内容时,事件会触发,这种做法可以大大降低 内存的耗费,特别使用于大数据量的文件。 
  24.  * @version 2014-9-2 
  25.  */  
  26. public abstract class ExcelReader extends DefaultHandler {  
  27.   
  28.     // 共享字符串表  
  29.     private SharedStringsTable sst;  
  30.       
  31.     // 上一次的内容  
  32.     private String lastContents;  
  33.     private boolean nextIsString;  
  34.   
  35.     private int sheetIndex = -1;  
  36.     private List rowList = new ArrayList();  
  37.   
  38.     // 当前行  
  39.     private int curRow = 0;  
  40.     // 当前列  
  41.     private int curCol = 0;  
  42.     // 日期标志  
  43.     private boolean dateFlag;  
  44.     // 数字标志  
  45.     private boolean numberFlag;  
  46.   
  47.     private boolean isTElement;  
  48.   
  49.     /** 
  50.      * 遍历工作簿中所有的电子表格 
  51.      * @param filename 
  52.      * @throws Exception 
  53.      */  
  54.     public void process(String filename) throws Exception {  
  55.         OPCPackage pkg = OPCPackage.open(filename);  
  56.         XSSFReader r = new XSSFReader(pkg);  
  57.         SharedStringsTable sst = r.getSharedStringsTable();  
  58.         XMLReader parser = fetchSheetParser(sst);  
  59.         Iterator sheets = r.getSheetsData();  
  60.         while (sheets.hasNext()) {  
  61.             curRow = 0;  
  62.             sheetIndex++;  
  63.             InputStream sheet = sheets.next();  
  64.             InputSource sheetSource = new InputSource(sheet);  
  65.             parser.parse(sheetSource);  
  66.             sheet.close();  
  67.         }  
  68.     }  
  69.   
  70.     /** 
  71.      * 只遍历一个电子表格,其中sheetId为要遍历的sheet索引,从1开始,1-3 
  72.      * @param filename 
  73.      * @param sheetId 
  74.      * @throws Exception 
  75.      */  
  76.     public void process(String filename, int sheetId) throws Exception {  
  77.         OPCPackage pkg = OPCPackage.open(filename);  
  78.         XSSFReader r = new XSSFReader(pkg);  
  79.         SharedStringsTable sst = r.getSharedStringsTable();  
  80.         XMLReader parser = fetchSheetParser(sst);  
  81.         // 根据 rId# 或 rSheet# 查找sheet  
  82.         InputStream sheet2 = r.getSheet("rId" + sheetId);  
  83.         sheetIndex++;  
  84.         InputSource sheetSource = new InputSource(sheet2);  
  85.         parser.parse(sheetSource);  
  86.         sheet2.close();  
  87.     }  
  88.   
  89.     public XMLReader fetchSheetParser(SharedStringsTable sst)  
  90.             throws SAXException {  
  91.         XMLReader parser = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");  
  92.         this.sst = sst;  
  93.         parser.setContentHandler(this);  
  94.         return parser;  
  95.     }  
  96.   
  97.     public void startElement(String uri, String localName, String name,  
  98.             Attributes attributes) throws SAXException {  
  99.   
  100. //      System.out.println("startElement: " + localName + ", " + name + ", " + attributes);  
  101.   
  102.         // c => 单元格  
  103.         if ("c".equals(name)) {  
  104.             // 如果下一个元素是 SST 的索引,则将nextIsString标记为true  
  105.             String cellType = attributes.getValue("t");  
  106.             if ("s".equals(cellType)) {  
  107.                 nextIsString = true;  
  108.             } else {  
  109.                 nextIsString = false;  
  110.             }  
  111.             // 日期格式  
  112.             String cellDateType = attributes.getValue("s");  
  113.             if ("1".equals(cellDateType)) {  
  114.                 dateFlag = true;  
  115.             } else {  
  116.                 dateFlag = false;  
  117.             }  
  118.             String cellNumberType = attributes.getValue("s");  
  119.             if ("2".equals(cellNumberType)) {  
  120.                 numberFlag = true;  
  121.             } else {  
  122.                 numberFlag = false;  
  123.             }  
  124.   
  125.         }  
  126.         // 当元素为t时  
  127.         if ("t".equals(name)) {  
  128.             isTElement = true;  
  129.         } else {  
  130.             isTElement = false;  
  131.         }  
  132.   
  133.         // 置空  
  134.         lastContents = "";  
  135.     }  
  136.   
  137.     public void endElement(String uri, String localName, String name)  
  138.             throws SAXException {  
  139.   
  140. //      System.out.println("endElement: " + localName + ", " + name);  
  141.   
  142.         // 根据SST的索引值的到单元格的真正要存储的字符串  
  143.         // 这时characters()方法可能会被调用多次  
  144.         if (nextIsString) {  
  145.             try {  
  146.                 int idx = Integer.parseInt(lastContents);  
  147.                 lastContents = new XSSFRichTextString(sst.getEntryAt(idx))  
  148.                         .toString();  
  149.             } catch (Exception e) {  
  150.   
  151.             }  
  152.         }  
  153.         // t元素也包含字符串  
  154.         if (isTElement) {  
  155.             String value = lastContents.trim();  
  156.             rowList.add(curCol, value);  
  157.             curCol++;  
  158.             isTElement = false;  
  159.             // v => 单元格的值,如果单元格是字符串则v标签的值为该字符串在SST中的索引  
  160.             // 将单元格内容加入rowlist中,在这之前先去掉字符串前后的空白符  
  161.         } else if ("v".equals(name)) {  
  162.             String value = lastContents.trim();  
  163.             value = value.equals("") ? " " : value;  
  164.             try {  
  165.                 // 日期格式处理  
  166.                 if (dateFlag) {  
  167.                     Date date = HSSFDateUtil.getJavaDate(Double.valueOf(value));  
  168.                     SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");  
  169.                     value = dateFormat.format(date);  
  170.                 }  
  171.                 // 数字类型处理  
  172.                 if (numberFlag) {  
  173.                     BigDecimal bd = new BigDecimal(value);  
  174.                     value = bd.setScale(3, BigDecimal.ROUND_UP).toString();  
  175.                 }  
  176.             } catch (Exception e) {  
  177.                 // 转换失败仍用读出来的值  
  178.             }  
  179.             rowList.add(curCol, value);  
  180.             curCol++;  
  181.         } else {  
  182.             // 如果标签名称为 row ,这说明已到行尾,调用 optRows() 方法  
  183.             if (name.equals("row")) {  
  184.                 getRows(sheetIndex + 1, curRow, rowList);  
  185.                 rowList.clear();  
  186.                 curRow++;  
  187.                 curCol = 0;  
  188.             }  
  189.         }  
  190.   
  191.     }  
  192.   
  193.     public void characters(char[] ch, int start, int length)  
  194.             throws SAXException {  
  195.         // 得到单元格内容的值  
  196.         lastContents += new String(ch, start, length);  
  197.     }  
  198.   
  199.     /** 
  200.      * 获取行数据回调 
  201.      * @param sheetIndex 
  202.      * @param curRow 
  203.      * @param rowList 
  204.      */  
  205.     public abstract void getRows(int sheetIndex, int curRow, List rowList);  
  206.   
  207.     /** 
  208.      * 测试方法 
  209.      */  
  210.     public static void main(String[] args) throws Exception {  
  211.   
  212. String file = "E:/导入测试数据.xlsx";  
  213.   
  214. ExcelReader reader = new ExcelReader() {  
  215.     public void getRows(int sheetIndex, int curRow, List rowList) {  
  216.           
  217.         System.out.println("Sheet:" + sheetIndex + ", Row:" + curRow + ", Data:" +rowList);  
  218.           
  219.     }  
  220. };  
  221. reader.process(file, 1);  
  222.   
  223.     }  
  224.   }

你可能感兴趣的:(POI读取excel大量数据)