JAVA读大数据量Excel


https://blog.csdn.net/zp19890228/article/details/41822617

[java]  view plain  copy
  1. import java.io.File;  
  2. import java.io.IOException;  
  3. import java.io.InputStream;  
  4. import java.util.Arrays;  
  5. import java.util.Date;  
  6.   
  7. import org.apache.commons.lang3.time.DateFormatUtils;  
  8. import org.apache.poi.hssf.usermodel.HSSFDateUtil;  
  9. import org.apache.poi.openxml4j.exceptions.OpenXML4JException;  
  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.model.StylesTable;  
  14. import org.apache.poi.xssf.usermodel.XSSFCellStyle;  
  15. import org.apache.poi.xssf.usermodel.XSSFRichTextString;  
  16. import org.xml.sax.Attributes;  
  17. import org.xml.sax.ContentHandler;  
  18. import org.xml.sax.InputSource;  
  19. import org.xml.sax.SAXException;  
  20. import org.xml.sax.XMLReader;  
  21. import org.xml.sax.helpers.DefaultHandler;  
  22. import org.xml.sax.helpers.XMLReaderFactory;  
  23.   
  24. public abstract class BigExcelReader{  
  25.       
  26.     enum xssfDataType {  
  27.         BOOL, ERROR, FORMULA, INLINESTR, SSTINDEX, NUMBER,  
  28.     }  
  29.       
  30.     public static final int ERROR = 1;  
  31.     public static final int BOOLEAN = 1;  
  32.     public static final int NUMBER = 2;  
  33.     public static final int STRING = 3;  
  34.     public static final int DATE = 4;  
  35.     public static final String DATE_FORMAT_STR = "yyyy-MM-dd HH:mm:ss";  
  36.       
  37.       
  38. //  private DataFormatter formatter = new DataFormatter();  
  39.     private InputStream sheet;  
  40.     private XMLReader parser;  
  41.     private InputSource sheetSource;  
  42.     private int index = 0;  
  43.       
  44.     /** 
  45.      * 读大数据量Excel 
  46.      *  
  47.      * @param filename 文件名 
  48.      * @param maxColNum 读取的最大列数 
  49.      * @throws IOException 
  50.      * @throws OpenXML4JException 
  51.      * @throws SAXException 
  52.      */  
  53.     public BigExcelReader(String filename) throws IOException, OpenXML4JException, SAXException{  
  54.         OPCPackage pkg = OPCPackage.open(filename);  
  55.         init(pkg);  
  56.     }  
  57.       
  58.     /** 
  59.      * 读大数据量Excel 
  60.      *  
  61.      * @param file Excel文件 
  62.      * @param maxColNum 读取的最大列数 
  63.      * @throws IOException 
  64.      * @throws OpenXML4JException 
  65.      * @throws SAXException 
  66.      */  
  67.     public BigExcelReader(File file) throws IOException, OpenXML4JException, SAXException{  
  68.         OPCPackage pkg = OPCPackage.open(file);  
  69.         init(pkg);  
  70.     }  
  71.       
  72.     /** 
  73.      * 读大数据量Excel 
  74.      *  
  75.      * @param in Excel文件输入流 
  76.      * @throws IOException 
  77.      * @throws OpenXML4JException 
  78.      * @throws SAXException 
  79.      */  
  80.     public BigExcelReader(InputStream in) throws IOException, OpenXML4JException, SAXException{  
  81.         OPCPackage pkg = OPCPackage.open(in);  
  82.         init(pkg);  
  83.     }  
  84.       
  85.     /** 
  86.      * 初始化 将Excel转换为XML 
  87.      *  
  88.      * @param pkg 
  89.      * @throws IOException 
  90.      * @throws OpenXML4JException 
  91.      * @throws SAXException 
  92.      */  
  93.     private void init(OPCPackage pkg) throws IOException, OpenXML4JException, SAXException{  
  94.         XSSFReader xssfReader = new XSSFReader(pkg);  
  95.         SharedStringsTable sharedStringsTable = xssfReader.getSharedStringsTable();  
  96.         StylesTable stylesTable = xssfReader.getStylesTable();  
  97.         sheet = xssfReader.getSheet("rId1");  
  98.         parser = fetchSheetParser(sharedStringsTable, stylesTable);  
  99.         sheetSource = new InputSource(sheet);  
  100.     }  
  101.       
  102.     /** 
  103.      * 执行解析操作 
  104.      *  
  105.      * @return 读取的Excel行数 
  106.      */  
  107.     public int parse(){  
  108.         try {  
  109.             parser.parse(sheetSource);  
  110.         }   
  111.         catch (IOException e) {  
  112.             e.printStackTrace();  
  113.         }   
  114.         catch (SAXException e) {  
  115.             e.printStackTrace();  
  116.         }  
  117.         finally{  
  118.             if(sheet != null){  
  119.                 try {  
  120.                     sheet.close();  
  121.                 } catch (IOException e) {  
  122.                     e.printStackTrace();  
  123.                 }  
  124.             }  
  125.         }  
  126.         return index;  
  127.     }  
  128.       
  129.     private XMLReader fetchSheetParser(SharedStringsTable sharedStringsTable, StylesTable stylesTable) throws SAXException {  
  130.         XMLReader parser =  
  131.             XMLReaderFactory.createXMLReader(  
  132.                     "org.apache.xerces.parsers.SAXParser"  
  133.             );  
  134.         ContentHandler handler = new SheetHandler(sharedStringsTable, stylesTable);  
  135.         parser.setContentHandler(handler);  
  136.         return parser;  
  137.     }  
  138.       
  139.     /** 
  140.      * SAX解析的处理类 
  141.      * 每解析一行数据后通过outputRow(String[] datas, int[] rowTypes, int rowIndex)方法进行输出 
  142.      *  
  143.      * @author zpin 
  144.      */  
  145.     private class SheetHandler extends DefaultHandler {  
  146.         private SharedStringsTable sharedStringsTable; // 存放映射字符串  
  147.         private StylesTable stylesTable;// 存放单元格样式  
  148.         private String readValue;// 存放读取值  
  149.         private xssfDataType dataType;// 单元格类型  
  150.         private String[] rowDatas;// 存放一行中的所有数据  
  151.         private int[] rowTypes;// 存放一行中所有数据类型  
  152.         private int colIdx;// 当前所在列  
  153.           
  154.         private short formatIndex;  
  155. //      private String formatString;// 对数值型的数据直接读为数值,不对其格式化,所以隐掉此处  
  156.           
  157.         private SheetHandler(SharedStringsTable sst,StylesTable stylesTable) {  
  158.             this.sharedStringsTable = sst;  
  159.             this.stylesTable = stylesTable;  
  160.         }  
  161.           
  162.         public void startElement(String uri, String localName, String name,  
  163.                 Attributes attributes) throws SAXException {  
  164.             if(name.equals("c")) {// c > 单元格  
  165.                 colIdx = getColumn(attributes);  
  166.                 String cellType = attributes.getValue("t");  
  167.                 String cellStyle = attributes.getValue("s");  
  168.                   
  169.                 this.dataType = xssfDataType.NUMBER;  
  170.                 if ("b".equals(cellType)){  
  171.                     this.dataType = xssfDataType.BOOL;  
  172.                 }  
  173.                 else if ("e".equals(cellType)){  
  174.                     this.dataType = xssfDataType.ERROR;  
  175.                 }  
  176.                 else if ("inlineStr".equals(cellType)){  
  177.                     this.dataType = xssfDataType.INLINESTR;  
  178.                 }  
  179.                 else if ("s".equals(cellType)){  
  180.                     this.dataType = xssfDataType.SSTINDEX;  
  181.                 }  
  182.                 else if ("str".equals(cellType)){  
  183.                     this.dataType = xssfDataType.FORMULA;  
  184.                 }  
  185.                 else if(cellStyle != null){  
  186.                     int styleIndex = Integer.parseInt(cellStyle);    
  187.                     XSSFCellStyle style = stylesTable.getStyleAt(styleIndex);    
  188.                     this.formatIndex = style.getDataFormat();    
  189. //                  this.formatString = style.getDataFormatString();    
  190.                 }  
  191.             }  
  192.             // 解析到一行的开始处时,初始化数组  
  193.             else if(name.equals("row")){  
  194.                 int cols = getColsNum(attributes);// 获取该行的单元格数  
  195.                 rowDatas = new String[cols];  
  196.                 rowTypes = new int[cols];  
  197.             }  
  198.             readValue = "";  
  199.         }  
  200.           
  201.         public void endElement(String uri, String localName, String name)  
  202.                 throws SAXException {  
  203.             if(name.equals("v")) { // 单元格的值  
  204.                 switch(this.dataType){  
  205.                     case BOOL: {  
  206.                         char first = readValue.charAt(0);  
  207.                         rowDatas[colIdx] = first == '0' ? "FALSE" : "TRUE";  
  208.                         rowTypes[colIdx] = BOOLEAN;  
  209.                         break;  
  210.                     }  
  211.                     case ERROR: {  
  212.                         rowDatas[colIdx] = "ERROR:" + readValue.toString();  
  213.                         rowTypes[colIdx] = ERROR;  
  214.                         break;  
  215.                     }  
  216.                     case INLINESTR: {  
  217.                         rowDatas[colIdx] = new XSSFRichTextString(readValue).toString();  
  218.                         rowTypes[colIdx] = STRING;  
  219.                         break;  
  220.                     }  
  221.                     case SSTINDEX:{  
  222.                         int idx = Integer.parseInt(readValue);    
  223.                         rowDatas[colIdx] = new XSSFRichTextString(sharedStringsTable.getEntryAt(idx)).toString();  
  224.                         rowTypes[colIdx] = STRING;  
  225.                         break;  
  226.                     }  
  227.                     case FORMULA:{  
  228.                         rowDatas[colIdx] = readValue;  
  229.                         rowTypes[colIdx] = STRING;  
  230.                         break;  
  231.                     }  
  232.                     case NUMBER:{  
  233.                         // 判断是否是日期格式    
  234.                         if (HSSFDateUtil.isADateFormat(formatIndex, readValue)) {    
  235.                             Double d = Double.parseDouble(readValue);    
  236.                             Date date = HSSFDateUtil.getJavaDate(d);    
  237.                             rowDatas[colIdx] = DateFormatUtils.format(date, DATE_FORMAT_STR);  
  238.                             rowTypes[colIdx] = DATE;  
  239.                         }   
  240. //                      else if (formatString != null){  
  241. //                          cellData.value = formatter.formatRawCellContents(Double.parseDouble(cellValue), formatIndex, formatString);  
  242. //                          cellData.dataType = NUMBER;  
  243. //                      }  
  244.                         else{  
  245.                             rowDatas[colIdx] = readValue;  
  246.                             rowTypes[colIdx] = NUMBER;  
  247.                         }  
  248.                         break;  
  249.                     }  
  250.                 }  
  251.             }  
  252.             // 当解析的一行的末尾时,输出数组中的数据  
  253.             else if(name.equals("row")){  
  254.                 outputRow(rowDatas, rowTypes, index++);  
  255.             }  
  256.         }  
  257.   
  258.         public void characters(char[] ch, int start, int length)  
  259.                 throws SAXException {  
  260.             readValue += new String(ch, start, length);  
  261.         }  
  262.     }  
  263.       
  264.     /** 
  265.      * 输出每一行的数据 
  266.      *  
  267.      * @param datas 数据 
  268.      * @param rowTypes 数据类型 
  269.      * @param rowIndex 所在行 
  270.      */  
  271.     protected abstract void outputRow(String[] datas, int[] rowTypes, int rowIndex);  
  272.       
  273.     private int getColumn(Attributes attrubuts) {    
  274.         String name = attrubuts.getValue("r");   
  275.         int column = -1;    
  276.         for (int i = 0; i < name.length(); ++i) {  
  277.             if (Character.isDigit(name.charAt(i))) {  
  278.                 break;  
  279.             }  
  280.             int c = name.charAt(i);    
  281.             column = (column + 1) * 26 + c - 'A';    
  282.         }    
  283.         return column;    
  284.     }  
  285.       
  286.     private int getColsNum(Attributes attrubuts){  
  287.         String spans = attrubuts.getValue("spans");  
  288.         String cols = spans.substring(spans.indexOf(":") + 1);  
  289.         return Integer.parseInt(cols);  
  290.     }  
  291. }  
[java]  view plain  copy
  1. import java.util.Arrays;  
  2.   
  3. public class BigExcelReaderTest {  
  4.     public static void main(String[] args) throws Exception{  
  5.         String filepath = "D:\\OA办公系统.xlsx";  
  6.         BigExcelReader reader = new BigExcelReader(filepath) {  
  7.             @Override  
  8.             protected void outputRow(String[] datas, int[] rowTypes, int rowIndex) {  
  9.                 // 此处输出每一行的数据  
  10.                 System.out.println(Arrays.toString(datas));  
  11.             }  
  12.         };  
  13.         // 执行解析  
  14.         reader.parse();  
  15.     }  
  16. }  

引用jar包如下



本文引用了 解决POI读取Excel内存溢出的问题 博客的部分内容,并对输出方式进行优化,方便数据的读取


猜你喜欢

转载自blog.csdn.net/dufufd/article/details/79918290