JAVA Apache POI 之sax 解析10万级大数量数据

Posted 史上最强的弟子

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA Apache POI 之sax 解析10万级大数量数据相关的知识,希望对你有一定的参考价值。

第一步让我们来看看我们的大量数据的excel 文件

好的下面第二步看一下代码:

package com.chinait.utils;  
  
/**
 * 写这个东西主要是最近做了一个联通的数据迁移工作,他们就是这样导出的数据,所以我们写了这个代码。
 * 还有一个就是网上n 多都是半成品,代码不能直接运行,我这个代码能够直接运行。
 * java poi 之sax 解析10万级大数量数据,其实百万,千万都是可以的,
 * 但是想到这么大的数据一般不会使用excel 进行导入数据的行为,所以我采用了这个方法只是针对于10万级数据,
 * 宁外,虚拟机的堆内存需要设置大一些,不然会报内存溢出。
 * 支持多个sheet 数据一起导入
 * 支持按照数据量范围取值
 */
  
import java.io.InputStream;  
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Pattern;  
  
import org.apache.commons.lang.StringUtils;  
import org.apache.poi.openxml4j.opc.OPCPackage;  
import org.apache.poi.xssf.eventusermodel.XSSFReader;  
import org.apache.poi.xssf.model.SharedStringsTable;  
import org.apache.poi.xssf.usermodel.XSSFRichTextString;  
import org.xml.sax.Attributes;  
import org.xml.sax.ContentHandler;  
import org.xml.sax.InputSource;  
import org.xml.sax.SAXException;  
import org.xml.sax.XMLReader;  
import org.xml.sax.helpers.DefaultHandler;  
import org.xml.sax.helpers.XMLReaderFactory;  
  
public class MyExcel2007ForPaging_high   
        private static List<Map<String,String>> dataListT;
        private final int startRow;  
        private final int endRow;  
        private int currentRow = 0;  
        private final String filename;  
        private static Map<String,String> map;
        static char[] strChar ;  
        /**
         * 构造方法
         */
        public MyExcel2007ForPaging_high(String filename,int startRow,int endRow) throws Exception
        	dataListT = new ArrayList<>();
            if(StringUtils.isEmpty(filename)) throw new Exception("文件名不能空");  
            this.filename = filename;  
            this.startRow = startRow;  
            this.endRow = endRow+1;  
            processSheet();  
          
        /** 
         * 指定获取第一个sheet 
         * @param filename 
         * @throws Exception 
         */  
        private void processSheet() throws Exception   
            OPCPackage pkg = OPCPackage.open(filename);  
            XSSFReader r = new XSSFReader( pkg );  
            SharedStringsTable sst = r.getSharedStringsTable();  
            XMLReader parser = fetchSheetParser(sst);   
            Iterator<InputStream> it = r.getSheetsData();
            while(it.hasNext())
            	 map = null;
            	 InputStream sheet1 = it.next();  
                 InputSource sheetSource = new InputSource(sheet1);  
                 parser.parse(sheetSource);  
                 sheet1.close();  
            
          
        /**
         * 加载sax 解析器
         * @param sst
         * @return
         * @throws SAXException
         */
        private XMLReader fetchSheetParser(SharedStringsTable sst) throws SAXException   
            XMLReader parser =  
                XMLReaderFactory.createXMLReader(  
                        "org.apache.xerces.parsers.SAXParser"  
                );  
            ContentHandler handler = new PagingHandler(sst);  
            parser.setContentHandler(handler);  
            return parser;  
          
  
        /**  
         * See org.xml.sax.helpers.DefaultHandler javadocs  
         */  
        private  class PagingHandler extends DefaultHandler   
            private SharedStringsTable sst;  
            private String lastContents;  
            private boolean nextIsString;  
            private String index = null;  
            private PagingHandler(SharedStringsTable sst)   
                this.sst = sst;  
            
            /**
             * 开始元素 (获取key 值)
             */
            @Override  
            public void startElement(String uri, String localName, String name,  
                    Attributes attributes) throws SAXException   
                if(name.equals("c")) 
                    index = attributes.getValue("r");
                    //判断是否是新的一行
                    if(Pattern.compile("^A[0-9]+$").matcher(index).find())  
                        if(map!=null&&isAccess()&&!map.isEmpty())  
                        	dataListT.add(map);
                        
                        map = new LinkedHashMap<>();
                        currentRow++; 
                      
                    if(isAccess())  
                        String cellType = attributes.getValue("t");  
                        if(cellType != null && cellType.equals("s"))   
                            nextIsString = true;  
                         else   
                            nextIsString = false;  
                          
                      
                  
                lastContents = "";  
              
            /**
             * 获取value 
             */
            @Override  
            public void endElement(String uri, String localName, String name)  
                    throws SAXException   
                if(isAccess())  
                    if(nextIsString)   
                        int idx = Integer.parseInt(lastContents);  
                        lastContents = new XSSFRichTextString(sst.getEntryAt(idx)).toString();  
                        nextIsString = false;  
                      
                    if(name.equals("v"))   
                    	map.put(index, lastContents);
                      
                  
                  
              
            @Override  
            public void characters(char[] ch, int start, int length)  
                    throws SAXException   
                if(isAccess())  
                    lastContents += new String(ch, start, length);  
                  
              
            @Override  
            public void endDocument ()throws SAXException  
                if(map!=null&&isAccess()&&!map.isEmpty())
                	dataListT.add(map);
                  
              
          
          
        private boolean isAccess()  
            if(currentRow>=startRow¤tRow<=endRow)  
                return true;  
              
            return false;  
        
        /**
         * 获取数据 并且填补字段值为空的数据
         * @return
         * @throws Exception
         */
        public List<Map<String,String>> getMyDataList() throws Exception
        	List<Map<String,String>> list = dataListT.subList(startRow, dataListT.size());
        	if(!list.isEmpty())
        		Map<String,String> map = dataListT.get(0);
        		List<String> com = data("A",map.size()-1);
        		for(int i=0;i<list.size();i++)
        			Map<String,String> returnMap = list.get(i);
        			for(String str:com)
        				boolean flag = true;
        				for(Entry<String,String> entry:returnMap.entrySet())
        					if(entry.getKey().contains(str))
        						//有
        						flag = false;
        						break;
        					
        				
        				if(flag)
	        				//没有
        					returnMap.put(str+(i+2), null);
        				
        			
        		
        	
            return list;  
          
       
        public static void main(String[] args) throws Exception 
        	MyExcel2007ForPaging_high reader = new MyExcel2007ForPaging_high("D://20000.xlsx",1,30000);  
            reader.getMyDataList();
        
        /**
         * 封装数据
         * @param str
         * @param counts
         * @return
         */
        public static List<String> data(String str,int counts)
        	List<String> list = new ArrayList<>();
        	list.add(str);
            for(int i=0;i<counts;i++)  
                strChar = str.toCharArray();  
                jinwei(0);  
                str = new String(strChar);  
                list.add(str);
            
            return list;
        
        //数字进位
        public static void jinwei(int index)
        	char a = 'A';
        	int aint =(int)('A');
        	if((strChar.length-1)-index>=0)
        		int sc = (int)strChar[(strChar.length-1)-index];
        		if(sc- 25 >= aint)
        			jinwei(index+1);
        			strChar[(strChar.length-1)-index] = a;
        		else
        			strChar[strChar.length-1-index] = (char)(sc+1);
        		
        	else
        		strChar[(strChar.length-1)-index+1] = a;
        		StringBuilder str = new StringBuilder();
        		str.append('A');
        		str.append(strChar);
        		strChar = str.toString().toCharArray();
        	
          
 
这是输出结果:

 写这个东西主要是最近做了一个联通的数据迁移工作,他们就是这样导出的数据,所以我们写了这个代码。

还有一个就是网上n 多都是半成品,代码不能直接运行,我这个代码能够直接运行。
java poi 之sax 解析10万级大数量数据,其实百万,千万都是可以的。
但是想到这么大的数据一般不会使用excel 进行导入数据的行为,所以我采用了这个方法只是针对于10万级数据。
宁外,虚拟机的堆内存需要设置大一些,不然会报内存溢出。
支持多个sheet 数据一起导入。
支持按照数据量范围取值。

支持原创,支持代码能运行的原创,谢谢!~

以上是关于JAVA Apache POI 之sax 解析10万级大数量数据的主要内容,如果未能解决你的问题,请参考以下文章

使用POI解析Excel时,出现org.xml.sax.SAXParseException: duplicate attribute 'o:relid'的解决办法

POI以SAX方式解析Excel2007大文件(包含空单元格的处理) Java生成CSV文件实例详解

Java解析Excel之POI

JAVA之DOM和SAX解析器

java解析XML① 之DOM解析和SAX解析(包含CDATA的问题)

Java 解析 Excel 工具 easyexcel