• 今天在做excel文件上传时,发现数据量超过10万条后,系统会出现内存溢出。 跟踪代码发现程序卡在如下中 Workbook workbook=WorkbookFactory.create(new File(path)); 通过poi的api发现此方法属于能对excel读写...

    今天在做excel文件上传时,发现数据量超过10万条后,系统会出现内存溢出。
    跟踪代码发现程序卡在如下代码这里:

    Workbook workbook=WorkbookFactory.create(new File(path));

    通过poi的api发现此方法属于能对excel读写,但是内存消耗大,速度较慢。
    在poi的官方文档中找到了读取大量数据的方法,但只能读数据,不能进行写操作。
    代码整理如下

    
    import java.io.InputStream;
    import java.util.Iterator;
    import java.util.LinkedHashMap;
    import java.util.Map;
    import java.util.Map.Entry;
    
    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.junit.Test;
    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;
    
    /**
     * 数据量比较大(8万条以上)的excel文件解析,将excel文件解析为 行列坐标-值的形式存入map中,此方式速度快,内存耗损小 但只能读取excle文件
     * 提供处理单个sheet方法 processOneSheet(String  filename) 以及处理多个sheet方法 processAllSheets(String  filename)
     * 只需传入文件路径+文件名即可  调用处理方法结束后,只需 接收LargeExcelFileReadUtil.getRowContents()返回值即可获得解析后的数据
     *
     */
    public class LargeExcelFileReadUtil  {
    
        private  LinkedHashMap<String, String>rowContents=new LinkedHashMap<String, String>(); 
        private  SheetHandler sheetHandler;
    
    public LinkedHashMap<String, String> getRowContents() {
            return rowContents;
        }
        public void setRowContents(LinkedHashMap<String, String> rowContents) {
            this.rowContents = rowContents;
        }
    
        public SheetHandler getSheetHandler() {
            return sheetHandler;
        }
        public void setSheetHandler(SheetHandler sheetHandler) {
            this.sheetHandler = sheetHandler;
        }
        //处理一个sheet
        public void processOneSheet(String filename) throws Exception {
            InputStream sheet2=null;
            OPCPackage pkg =null;
            try {
                    pkg = OPCPackage.open(filename);
                    XSSFReader r = new XSSFReader(pkg);
                    SharedStringsTable sst = r.getSharedStringsTable();
                    XMLReader parser = fetchSheetParser(sst);
                    sheet2 = r.getSheet("rId1");
                    InputSource sheetSource = new InputSource(sheet2);
                    parser.parse(sheetSource);
                    setRowContents(sheetHandler.getRowContents());
                    }catch (Exception e) {
                        e.printStackTrace();
                        throw e;
                        }finally{
                            if(pkg!=null){
                                pkg.close();
                                         }
                            if(sheet2!=null){
                                sheet2.close();
                                            }
                    }
        }
    //处理多个sheet
        public void processAllSheets(String filename) throws Exception {
            OPCPackage pkg =null;
            InputStream sheet=null;
            try{
                    pkg=OPCPackage.open(filename);
                    XSSFReader r = new XSSFReader( pkg );
                    SharedStringsTable sst = r.getSharedStringsTable();
                    XMLReader parser = fetchSheetParser(sst);
                    Iterator<InputStream> sheets = r.getSheetsData();
                    while(sheets.hasNext()) {
                        System.out.println("Processing new sheet:\n");
                        sheet = sheets.next();
                        InputSource sheetSource = new InputSource(sheet);
                        parser.parse(sheetSource);
                                            }
                }catch (Exception e) {
                        e.printStackTrace();
                        throw e;
                       }finally{
                           if(pkg!=null){
                               pkg.close();
                                     }
                           if(sheet!=null){
                               sheet.close();
                                        }
                                }
        }
    
        public XMLReader fetchSheetParser(SharedStringsTable sst) throws SAXException {
            XMLReader parser =
                XMLReaderFactory.createXMLReader(
                        "com.sun.org.apache.xerces.internal.parsers.SAXParser"
                );
            setSheetHandler(new SheetHandler(sst));
            ContentHandler handler = (ContentHandler) sheetHandler;
            parser.setContentHandler(handler);
            return parser;
        }
    
        /** 
         * See org.xml.sax.helpers.DefaultHandler javadocs 
         */
        //测试
        @Test
        public  void test ()throws Exception {
           Long time=System.currentTimeMillis();
            LargeExcelFileReadUtil example = new LargeExcelFileReadUtil();
    
            example.processOneSheet("C:/Users/Desktop/2018041310024112.xlsx");
            Long endtime=System.currentTimeMillis();
            LinkedHashMap<String, String>  map=example.getRowContents();
            Iterator<Entry<String, String>> it= map.entrySet().iterator();
            int count=0;
            String prePos="";
            while (it.hasNext()){
                Map.Entry<String, String> entry=(Map.Entry<String, String>)it.next();
                String pos=entry.getKey();
                if(!pos.substring(1).equals(prePos)){
                    prePos=pos.substring(1);
                    count++;
                }
                System.out.println(pos+";"+entry.getValue());
            }
            System.out.println("解析数据"+count+"条;耗时"+(endtime-time)/1000+"秒");
        }
    }
    
    
    /**
    SheetHandler  类中处理从excle获取的数据,官方文档中 SheetHandler以内部类形式,为保证更新代码减少内部类class文件忘记打包,改为一般java类
    */
    import java.util.LinkedHashMap;
    
    import org.apache.poi.xssf.model.SharedStringsTable;
    import org.apache.poi.xssf.usermodel.XSSFRichTextString;
    import org.xml.sax.Attributes;
    import org.xml.sax.SAXException;
    import org.xml.sax.helpers.DefaultHandler;
    
    public class SheetHandler  extends DefaultHandler{
    
        private SharedStringsTable sst;
        private String lastContents;
        private boolean nextIsString;
        private String  cellPosition;
        private  LinkedHashMap<String, String>rowContents=new LinkedHashMap<String, String>(); 
    
        public LinkedHashMap<String, String> getRowContents() {
            return rowContents;
        }
    
        public void setRowContents(LinkedHashMap<String, String> rowContents) {
            this.rowContents = rowContents;
        }
    
        public SheetHandler(SharedStringsTable sst) {
            this.sst = sst;
        }
    
        public void startElement(String uri, String localName, String name,
                Attributes attributes) throws SAXException {
            if(name.equals("c")) {
             //   System.out.print(attributes.getValue("r") + " - ");
                cellPosition=attributes.getValue("r");
                String cellType = attributes.getValue("t");
                if(cellType != null && cellType.equals("s")) {
                    nextIsString = true;
                } else {
                    nextIsString = false;
                }
            }
            // 清楚缓存内容
            lastContents = "";
        }
    
        public 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;
            }
    
            if(name.equals("v")) {
    //            System.out.println("lastContents:"+cellPosition+";"+lastContents);
                //数据读取结束后,将单元格坐标,内容存入map中
                if(!(cellPosition.length()==2)||(cellPosition.length()==2&&!"1".equals(cellPosition.substring(1)))){//不保存第一行数据
                    rowContents.put(cellPosition, lastContents);
                }
            }
        }
    
        public void characters(char[] ch, int start, int length)
                throws SAXException {
            lastContents += new String(ch, start, length);
        }
    }
    
    

    亲测可用,20多万条数据,4秒解析完,执行结果
    这里写图片描述
    poi jar包如下:
    这里写图片描述

    展开全文
  • maven依赖使用Poi4.1.1 <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>4.1.1</version> </depend...

    maven依赖使用Poi4.1.1

    <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>4.1.1</version>
        </dependency>
        
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>4.1.1</version>
        </dependency>
        
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml-schemas</artifactId>
            <version>4.1.1</version>
        </dependency>

    主要方法

    package com.poi.study;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.Map;
    
    import org.apache.poi.ooxml.util.SAXHelper;
    import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
    import org.apache.poi.openxml4j.opc.OPCPackage;
    import org.apache.poi.ss.usermodel.BuiltinFormats;
    import org.apache.poi.ss.usermodel.DataFormatter;
    import org.apache.poi.xssf.eventusermodel.XSSFReader;
    import org.apache.poi.xssf.model.SharedStringsTable;
    import org.apache.poi.xssf.model.StylesTable;
    import org.apache.poi.xssf.usermodel.XSSFCellStyle;
    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 javax.xml.parsers.ParserConfigurationException;
    public class ExcelEventUserModel {
        
        
        public static void processAllSheets(String filename, ExcelReadHandler excelReadHandler) {
            Iterator<InputStream> sheets = null;
            XMLReader parser = null;
            try {
                OPCPackage pkg = OPCPackage.open(filename);
                XSSFReader reader = new XSSFReader( pkg );
                SharedStringsTable sst = reader.getSharedStringsTable();
                StylesTable styleTable = reader.getStylesTable();
                parser = fetchSheetParser(sst, styleTable, excelReadHandler);
                sheets = reader.getSheetsData();
            } catch (IOException | OpenXML4JException | SAXException | ParserConfigurationException e) {
                throw new ExcelReadException("读取Excel报错");
            }
            
            while(sheets != null && sheets.hasNext()) {
                try(InputStream sheet = sheets.next();){
                    InputSource sheetSource = new InputSource(sheet);
                    parser.parse(sheetSource);
                } catch (IOException | SAXException e) {
                    throw new ExcelReadException("读取Excel中sheet表报错");
                }
            }
        }
        
        public static XMLReader fetchSheetParser(SharedStringsTable sst, StylesTable styleTable, ExcelReadHandler excelReadHandler) throws SAXException, ParserConfigurationException {
            XMLReader parser = SAXHelper.newXMLReader();
            ContentHandler handler = new SheetHandler(sst, styleTable, excelReadHandler);
            parser.setContentHandler(handler);
            return parser;
        }
        /**
         * See org.xml.sax.helpers.DefaultHandler javadocs
         */
        private static class SheetHandler extends DefaultHandler {
            
            /**
             * 单元格中的数据可能的数据类型
             */
            enum CellDataType {
                BOOL, ERROR, FORMULA, INLINESTR, SSTINDEX, NUMBER, DATE, NULL
            }
            
            private final DataFormatter formatter = new DataFormatter();
            
            private SharedStringsTable sst;                //excel中,若单元格内的内容是字符串,那么这些字符串都存在这个变量中
            private StylesTable styleTable;                //用于获取时间类型单元格的时间格式
            
            private String currentContents;                //当前单元格的内容
            private String ref;                            //当前单元格的位置
            private CellDataType cellDataType;            //当前单元格的类型
            private short formatIndex;                    //当前单元格为时间时的格式索引
            private String formatString;                //当前单元格为时间时的格式
            private Map<String, String> result = new HashMap<>();
            private ExcelReadHandler excelReadHandler;    //读取一行的回调
            
            private SheetHandler(SharedStringsTable sst, StylesTable styleTable, ExcelReadHandler excelReadHandler) {
                this.sst = sst;
                this.styleTable = styleTable;
                this.excelReadHandler = excelReadHandler;
            }
            
            /**
             * 这个方法在遇到一个xml文件的元素开始之前被触发,
             * 在这里,我们可以筛选出单元格,并提前取出单元格内存放的内容的类型
             */
            @Override
            public void startElement(String uri, String localName, String name,
                                     Attributes attributes) throws SAXException {
                // name为c表示遇到了单元格
                if(name.equals("c")) {
                    ref = attributes.getValue("r");
                    setNextDataType(attributes);
                }
                // 即将获取单元格的内容,所以置空该变量
                currentContents = "";
            }
            
            
            /**
             * 处理数据类型
             *
             * @param attributes 单元格参数
             */
            private void setNextDataType(Attributes attributes) {
                cellDataType = CellDataType.NUMBER; //cellType为空,则表示该单元格类型为数字
                formatIndex = -1;
                formatString = null;
                String cellType = attributes.getValue("t"); //单元格类型
                String cellStyleStr = attributes.getValue("s");
    
                if ("b".equals(cellType)) { //处理布尔值
                    cellDataType = CellDataType.BOOL;
                } else if ("e".equals(cellType)) {  //处理错误
                    cellDataType = CellDataType.ERROR;
                } else if ("inlineStr".equals(cellType)) {
                    cellDataType = CellDataType.INLINESTR;
                } else if ("s".equals(cellType)) { //处理字符串
                    cellDataType = CellDataType.SSTINDEX;
                } else if ("str".equals(cellType)) {
                    cellDataType = CellDataType.FORMULA;
                }
    
                if (cellStyleStr != null) { //处理日期
                    int styleIndex = Integer.parseInt(cellStyleStr);
                    XSSFCellStyle style = styleTable.getStyleAt(styleIndex);
                    formatIndex = style.getDataFormat();
                    formatString = style.getDataFormatString();
    
                    if (formatString == null) {
                        cellDataType = CellDataType.NULL;
                        formatString = BuiltinFormats.getBuiltinFormat(formatIndex);
                    }
    
                    if (formatString.contains("m/d/yy")) {
                        cellDataType = CellDataType.DATE;
                        formatString = "yyyy-MM-dd hh:mm:ss";
                    }
                }
            }
            
            private String getDataValue(String value) {
                String thisStr;
                switch (cellDataType) {
                    // 这几个的顺序不能随便交换,交换了很可能会导致数据错误
                    case BOOL: //布尔值
                        char first = value.charAt(0);
                        thisStr = first == '0' ? "FALSE" : "TRUE";
                        break;
                    case ERROR: //错误
                        thisStr = "\"ERROR:"   value   '"';
                        break;
                    case FORMULA: //公式
                        thisStr = '"'   value   '"';
                        break;
                    case INLINESTR:
                        XSSFRichTextString rtsi = new XSSFRichTextString(value);
                        thisStr = rtsi.toString();
                        break;
                    case SSTINDEX: //字符串
                        int idx = Integer.parseInt(value);
                        thisStr = sst.getItemAt(idx).getString();
                        break;
                    case NUMBER: //数字
                        if (formatString != null) {
                            thisStr = formatter.formatRawCellContents(Double.parseDouble(value), formatIndex, formatString).trim();
                        } else {
                            thisStr = value;
                        }
                        thisStr = thisStr.replace("_", "").trim();
                        break;
                    case DATE: //日期
                        thisStr = formatter.formatRawCellContents(Double.parseDouble(value), formatIndex, formatString);
                        // 对日期字符串作特殊处理,去掉T
                        thisStr = thisStr.replace("T", " ");
                        break;
                    default:
                        thisStr = " ";
                        break;
                }
                return thisStr;
            }
            
            /**
             * 第二个被触发,currentContents存储当前单元格的内容
             */
            @Override
            public void characters(char[] ch, int start, int length) {
                currentContents  = new String(ch, start, length);
            }
            
            /**
             * 第三个被触发,读取完单元格的内容后被执行
             */
            @Override
            public void endElement(String uri, String localName, String name)
                    throws SAXException {
                
                if(name.equals("v")) {
                    result.put(ref, getDataValue(currentContents));
                }
                
                if(name.equals("row")) {
                    excelReadHandler.processOneRow(result);
                    result.clear();
                }
            }
            
            
        }
        public static void main(String[] args) throws Exception {
            ExcelEventUserModel.processAllSheets("C:\\Users\\jinliujie\\Desktop\\createCell.xlsx", (result) -> {
                System.out.println(result);
            });
        }
    }

    ExcelReadException自定义异常

    package com.poi.study;
    
    public class ExcelReadException extends RuntimeException {
    
        /**
         * 
         */
        private static final long serialVersionUID = 1L;
    
        public ExcelReadException() {
            super();
        }
    
        public ExcelReadException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
            super(message, cause, enableSuppression, writableStackTrace);
        }
    
        public ExcelReadException(String message, Throwable cause) {
            super(message, cause);
        }
    
        public ExcelReadException(String message) {
            super(message);
        }
    
        public ExcelReadException(Throwable cause) {
            super(cause);
        }
        
        
    
    }
    

    ExcelReadHandler 读取一行的回调

    package com.poi.study;
    
    import java.util.Map;
    
    public interface ExcelReadHandler {
        
        void processOneRow(Map<String, String> row);
    
    }
    

    本文由博客一文多发平台 OpenWrite 发布!

    展开全文
  • 使用Poi读取大数据量excel的方法 支持2003和2007的版本
  • POI读取excel大量数据

    2016-11-30 20:56:08
    首先,给个原文地址:http://thinkgem.iteye.com/blog/2150940 import java.io.InputStream;  import java.math.BigDecimal;  import java.text.SimpleDateFormat;  ...import jav
    首先,给个原文地址: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<String> rowList = new ArrayList<String>();  
    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<InputStream> 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<String> 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<String> rowList) {  
    216.           
    217.         System.out.println("Sheet:" + sheetIndex + ", Row:" + curRow + ", Data:" +rowList);  
    218.           
    219.     }  
    220. };  
    221. reader.process(file, 1);  
    222.   
    223.     }  
    224.   }
    展开全文
  • java代码使用poi的API解决在读取大数据量Excel数据时候内存溢出的问题:首先我需要声明下面的工具类是在老袁博客(https://laoyuan.me/posts/java-read-big-excel-with-poi.html)基础上做了稍微的改造,我将老袁...

    java代码使用poi的API解决在读取大数据量的Excel数据时候内存溢出的问题:首先我需要声明下面的工具类是在老袁博客(https://laoyuan.me/posts/java-read-big-excel-with-poi.html)基础上做了稍微的改造,我将老袁的的工具类需要2个参数改成只需要一个参数就可以完成调用,当然你可以根据你自己的情况使用。
    下面是一个工具类,复制到自己的项目中直接调用即可:

    1、工具类

    package com.xxx.xxx.xxx;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.ArrayList;
    import java.util.List;
    
    import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
    import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
    import org.apache.poi.openxml4j.opc.OPCPackage;
    import org.apache.poi.xssf.eventusermodel.ReadOnlySharedStringsTable;
    import org.apache.poi.xssf.eventusermodel.XSSFReader;
    import org.apache.poi.xssf.eventusermodel.XSSFSheetXMLHandler;
    import org.apache.poi.xssf.eventusermodel.XSSFSheetXMLHandler.SheetContentsHandler;
    import org.apache.poi.xssf.model.StylesTable;
    import org.apache.poi.xssf.usermodel.XSSFComment;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.stereotype.Component;
    import org.xml.sax.InputSource;
    import org.xml.sax.SAXException;
    import org.xml.sax.XMLReader;
    import org.xml.sax.helpers.XMLReaderFactory;
    /**
     * 解析大数据量Excel工具类
     * @author RobinTime
     *
     */
    @Component
    public class ExcelParser {
        private static final Logger logger = LoggerFactory.getLogger(ExcelParser.class);
        /**
         * 表格默认处理器
         */
        private ISheetContentHandler contentHandler = new DefaultSheetHandler();
        /**
         * 读取数据
         */
        private List<String[]> datas = new ArrayList<String[]>();
    
        /**
         * 转换表格,默认为转换第一个表格
         * @param stream
         * @return
         * @throws InvalidFormatException
         * @throws IOException
         * @throws ParseException
         */
        public ExcelParser parse(InputStream stream)
                throws InvalidFormatException, IOException, ParseException {
            return parse(stream, 1);
        }
    
    
        /**
         * 
         * @param stream
         * @param sheetId:为要遍历的sheet索引,从1开始
         * @return
         * @throws InvalidFormatException
         * @throws IOException
         * @throws ParseException
         */
        public synchronized ExcelParser parse(InputStream stream, int sheetId)
                throws InvalidFormatException, IOException, ParseException {
            // 每次转换前都清空数据
            datas.clear();
            // 打开表格文件输入流
            OPCPackage pkg = OPCPackage.open(stream);
            try {
                // 创建表阅读器
                XSSFReader reader;
                try {
                    reader = new XSSFReader(pkg);
                } catch (OpenXML4JException e) {
                    logger.error("读取表格出错");
                    throw new ParseException(e.fillInStackTrace());
                }
    
                // 转换指定单元表
                InputStream shellStream = reader.getSheet("rId" + sheetId);
                try {
                    InputSource sheetSource = new InputSource(shellStream);
                    StylesTable styles = reader.getStylesTable();
                    ReadOnlySharedStringsTable strings = new ReadOnlySharedStringsTable(pkg);
                    getContentHandler().init(datas);// 设置读取出的数据
                    // 获取转换器
                    XMLReader parser = getSheetParser(styles, strings);
                    parser.parse(sheetSource);
                } catch (SAXException e) {
                    logger.error("读取表格出错");
                    throw new ParseException(e.fillInStackTrace());
                } finally {
                    shellStream.close();
                }
            } finally {
                pkg.close();
    
            }
            return this;
    
        }
    
        /**
         * 获取表格读取数据,获取数据前,需要先转换数据<br>
         * 此方法不会获取第一行数据
         * 
         * @return 表格读取数据
         */
        public List<String[]> getDatas() {
            return getDatas(true);
    
        }
    
        /**
         * 获取表格读取数据,获取数据前,需要先转换数据
         * 
         * @param dropFirstRow
         *            删除第一行表头记录
         * @return 表格读取数据
         */
        public List<String[]> getDatas(boolean dropFirstRow) {
            if (dropFirstRow && datas.size() > 0) {
                datas.remove(0);// 删除表头
            }
            return datas;
    
        }
    
        /**
         * 获取读取表格的转换器
         * 
         * @return 读取表格的转换器
         * @throws SAXException
         *             SAX错误
         */
        protected XMLReader getSheetParser(StylesTable styles, ReadOnlySharedStringsTable strings) throws SAXException {
            XMLReader parser = XMLReaderFactory.createXMLReader();
            parser.setContentHandler(new XSSFSheetXMLHandler(styles, strings, getContentHandler(), false));
            return parser;
        }
    
        public ISheetContentHandler getContentHandler() {
            return contentHandler;
        }
    
        public void setContentHandler(ISheetContentHandler contentHandler) {
            this.contentHandler = contentHandler;
        }
    
        /**
         * 表格转换错误
         */
        public class ParseException extends Exception {
            private static final long serialVersionUID = -2451526411018517607L;
    
            public ParseException(Throwable t) {
                super("表格转换错误", t);
            }
    
        }
    
        public interface ISheetContentHandler extends SheetContentsHandler {
    
            /**
             * 设置转换后的数据集,用于存放转换结果
             * 
             * @param datas
             *            转换结果
             */
            void init(List<String[]> datas);
        }
    
        /**
         * 默认表格解析handder
         */
        class DefaultSheetHandler implements ISheetContentHandler {
            /**
             * 读取数据
             */
            private List<String[]> datas;
            private int columsLength;
            // 读取行信息
            private String[] readRow;
            private ArrayList<String> fristRow = new ArrayList<String>();
    
            @Override
            public void init(List<String[]> datas) {
                this.datas = datas;
    //          this.columsLength = columsLength;
            }
    
            @Override
            public void startRow(int rowNum) {
                if (rowNum != 0) {
                    readRow = new String[columsLength];
                }
            }
    
            @Override
            public void endRow(int rowNum) {
            //将Excel第一行表头的列数当做数组的长度,要保证后续的行的列数不能超过这个长度,这是个约定。
                if (rowNum == 0) {
                    columsLength = fristRow.size();
                    readRow = fristRow.toArray(new String[fristRow.size()]);
                }else {
                    readRow = fristRow.toArray(new String[columsLength]);
                }
                datas.add(readRow.clone());
                readRow = null;
                fristRow.clear();
            }
    
            @Override
            public void cell(String cellReference, String formattedValue, XSSFComment comment) {
                int index = getCellIndex(cellReference);//转换A1,B1,C1等表格位置为真实索引位置
                try {
                    fristRow.set(index, formattedValue);
                } catch (IndexOutOfBoundsException e) {
                    int size = fristRow.size();
                    for (int i = index - size+1;i>0;i--){
                        fristRow.add(null);
                    }
                    fristRow.set(index,formattedValue);
                }
            }
    
            @Override
            public void headerFooter(String text, boolean isHeader, String tagName) {
            }
    
            /**
             * 转换表格引用为列编号
             * 
             * @param cellReference
             *            列引用
             * @return 表格列位置,从0开始算
             */
            public int getCellIndex(String cellReference) {
                String ref = cellReference.replaceAll("\\d+", "");
                int num = 0;
                int result = 0;
                for (int i = 0; i < ref.length(); i++) {
                    char ch = cellReference.charAt(ref.length() - i - 1);
                    num = (int) (ch - 'A' + 1);
                    num *= Math.pow(26, i);
                    result += num;
                }
                return result - 1;
            }
        }
    }

    2、调用

    File tempFile = new File(this.getClass().getClassLoader().getResource("").getPath() + "tempFile\\" + (new Date()).getTime() + ".xlsx");
    //传入一个路径产生流再将流传入工具类,返回解析对象,Excel的所有数据就被解析到List<String[]> 里面,遍历list任由你处置。
    FileInputStream inputStream = new FileInputStream(tempFile);
    ExcelParser parse = excelParser.parse(inputStream);
    List<String[]> datas = parse.getDatas();
    展开全文
  • POI读写大数据量EXCEL

    2018-05-07 17:38:19
    大数据量excel一般都是.xlsx格式的,网上使用POI读写的例子比较多,但是很少提到读写非常大数据量excel的例子,POI官网上提到XSSF有三种读写excelPOI地址:http://poi.apache.org/spreadsheet/index.html...

    另一篇文章http://www.cnblogs.com/tootwo2/p/8120053.html里面有xml的一些解释。

    大数据量的excel一般都是.xlsx格式的,网上使用POI读写的例子比较多,但是很少提到读写非常大数据量的excel的例子,POI官网上提到XSSF有三种读写excel,POI地址:http://poi.apache.org/spreadsheet/index.html。官网的图片:

    可以看到有三种模式:

    1、eventmodel方式,基于事件驱动,SAX的方式解析excel(.xlsx是基于OOXML的),CPU和内存消耗非常低,但是只能读不能写

    2、usermodel,就是我们一般使用的方式,这种方式可以读可以写,但是CPU和内存消耗非常大

    3、SXSSF,POI3.8以后开始支持,这种方式只能写excel

    下面介绍下使用方式(官网地址:http://poi.apache.org/spreadsheet/how-to.html):

    第一种方式:

    pom文件需要添加依赖:

    复制代码
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>3.15</version>
    </dependency>
    <dependency>
        <groupId>xerces</groupId>
        <artifactId>xerces</artifactId>
        <version>2.4.0</version>
    </dependency>
    复制代码

    java官网示例代码:

    复制代码
    package excel;
    
    import java.io.InputStream;
    import java.util.Iterator;
    
    import org.apache.poi.xssf.eventusermodel.XSSFReader;
    import org.apache.poi.xssf.model.SharedStringsTable;
    import org.apache.poi.xssf.usermodel.XSSFRichTextString;
    import org.apache.poi.openxml4j.opc.OPCPackage;
    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 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);
    
            // To look up the Sheet Name / Sheet Order / rID,
            //  you need to process the core Workbook stream.
            // Normally it's of the form rId# or rSheet#
            InputStream sheet2 = r.getSheet("rId2");
            InputSource sheetSource = new InputSource(sheet2);
            parser.parse(sheetSource);
            sheet2.close();
        }
    
        public void processAllSheets(String filename) throws Exception {
            OPCPackage pkg = OPCPackage.open(filename);
            XSSFReader r = new XSSFReader( pkg );
            SharedStringsTable sst = r.getSharedStringsTable();
            
            XMLReader parser = fetchSheetParser(sst);
    
            Iterator<InputStream> sheets = r.getSheetsData();
            while(sheets.hasNext()) {
                System.out.println("Processing new sheet:\n");
                InputStream sheet = sheets.next();
                InputSource sheetSource = new InputSource(sheet);
                parser.parse(sheetSource);
                sheet.close();
                System.out.println("");
            }
        }
    
        public XMLReader fetchSheetParser(SharedStringsTable sst) throws SAXException {
            XMLReader parser =
                XMLReaderFactory.createXMLReader(
                        "com.sun.org.apache.xerces.internal.parsers.SAXParser"
                );
            ContentHandler handler = new SheetHandler(sst);
            parser.setContentHandler(handler);
            return parser;
        }
    
        /** 
         * See org.xml.sax.helpers.DefaultHandler javadocs 
         */
        private static class SheetHandler extends DefaultHandler {
            private SharedStringsTable sst;
            private String lastContents;
            private boolean nextIsString;
            
            private SheetHandler(SharedStringsTable sst) {
                this.sst = sst;
            }
            
            public void startElement(String uri, String localName, String name,
                    Attributes attributes) throws SAXException {
                // c => cell
                if(name.equals("c")) {
                    // Print the cell reference
                    System.out.print(attributes.getValue("r") + " - ");
                    // Figure out if the value is an index in the SST
                    String cellType = attributes.getValue("t");
                    if(cellType != null && cellType.equals("s")) {
                        nextIsString = true;
                    } else {
                        nextIsString = false;
                    }
                }
                // Clear contents cache
                lastContents = "";
            }
            
            public void endElement(String uri, String localName, String name)
                    throws SAXException {
                // Process the last contents as required.
                // Do now, as characters() may be called more than once
                if(nextIsString) {
                    int idx = Integer.parseInt(lastContents);
                    lastContents = new XSSFRichTextString(sst.getEntryAt(idx)).toString();
                    nextIsString = false;
                }
    
                // v => contents of a cell
                // Output after we've seen the string contents
                if(name.equals("v")) {
                    System.out.println(lastContents);
                }
            }
    
            public 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();
            System.out.println("11");
            example.processOneSheet(args[0]);
            example.processAllSheets(args[0]);
        }
    }
    复制代码

    运行的时候使用本地的文件地址替代main函数里面的参数就可以运行(亲测可以)。

    第三种方式:

    其核心是减少存储在内存当中的数据,达到一定行数就存储到硬盘的临时文件中。

    pom文件需要增加依赖:

    <dependency>
        <groupId>xerces</groupId>
        <artifactId>xercesImpl</artifactId>
        <version>2.11.0</version>
    </dependency>

    java代码如下:

    复制代码
    package excel;
    
    
    //import junit.framework.Assert;
    import java.io.FileOutputStream;
    
    import org.apache.poi.ss.usermodel.Cell;
    import org.apache.poi.ss.usermodel.Row;
    import org.apache.poi.ss.usermodel.Sheet;
    import org.apache.poi.ss.usermodel.Workbook;
    import org.apache.poi.ss.util.CellReference;
    import org.apache.poi.xssf.streaming.SXSSFWorkbook;
    
    public class SXSSFDemo {
        public static void main(String[] args) throws Throwable {
            
            SXSSFWorkbook wb = new SXSSFWorkbook(100); // 在内存当中保持 100 行 , 超过的数据放到硬盘中
            Sheet sh = wb.createSheet();
            for(int rownum = 0; rownum < 10000; rownum++){
                Row row = sh.createRow(rownum);
                for(int cellnum = 0; cellnum < 10; cellnum++){
                    Cell cell = row.createCell(cellnum);
                    String address = new CellReference(cell).formatAsString();
                    cell.setCellValue(address);
                }
    
            }     
            
            FileOutputStream out = new FileOutputStream("/Users/tootwo2/Documents/sxssf.xlsx");
            wb.write(out);
            out.close();
    
            // dispose of temporary files backing this workbook on disk
            wb.dispose();
        }
    
    }
    转载:

    另一篇文章http://www.cnblogs.com/tootwo2/p/8120053.html里面有xml的一些解释。

    大数据量的excel一般都是.xlsx格式的,网上使用POI读写的例子比较多,但是很少提到读写非常大数据量的excel的例子,POI官网上提到XSSF有三种读写excel,POI地址:http://poi.apache.org/spreadsheet/index.html。官网的图片:

    可以看到有三种模式:

    1、eventmodel方式,基于事件驱动,SAX的方式解析excel(.xlsx是基于OOXML的),CPU和内存消耗非常低,但是只能读不能写

    2、usermodel,就是我们一般使用的方式,这种方式可以读可以写,但是CPU和内存消耗非常大

    3、SXSSF,POI3.8以后开始支持,这种方式只能写excel

    下面介绍下使用方式(官网地址:http://poi.apache.org/spreadsheet/how-to.html):

    第一种方式:

    pom文件需要添加依赖:

    复制代码
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>3.15</version>
    </dependency>
    <dependency>
        <groupId>xerces</groupId>
        <artifactId>xerces</artifactId>
        <version>2.4.0</version>
    </dependency>
    复制代码

    java官网示例代码:

    复制代码
    package excel;
    
    import java.io.InputStream;
    import java.util.Iterator;
    
    import org.apache.poi.xssf.eventusermodel.XSSFReader;
    import org.apache.poi.xssf.model.SharedStringsTable;
    import org.apache.poi.xssf.usermodel.XSSFRichTextString;
    import org.apache.poi.openxml4j.opc.OPCPackage;
    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 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);
    
            // To look up the Sheet Name / Sheet Order / rID,
            //  you need to process the core Workbook stream.
            // Normally it's of the form rId# or rSheet#
            InputStream sheet2 = r.getSheet("rId2");
            InputSource sheetSource = new InputSource(sheet2);
            parser.parse(sheetSource);
            sheet2.close();
        }
    
        public void processAllSheets(String filename) throws Exception {
            OPCPackage pkg = OPCPackage.open(filename);
            XSSFReader r = new XSSFReader( pkg );
            SharedStringsTable sst = r.getSharedStringsTable();
            
            XMLReader parser = fetchSheetParser(sst);
    
            Iterator<InputStream> sheets = r.getSheetsData();
            while(sheets.hasNext()) {
                System.out.println("Processing new sheet:\n");
                InputStream sheet = sheets.next();
                InputSource sheetSource = new InputSource(sheet);
                parser.parse(sheetSource);
                sheet.close();
                System.out.println("");
            }
        }
    
        public XMLReader fetchSheetParser(SharedStringsTable sst) throws SAXException {
            XMLReader parser =
                XMLReaderFactory.createXMLReader(
                        "com.sun.org.apache.xerces.internal.parsers.SAXParser"
                );
            ContentHandler handler = new SheetHandler(sst);
            parser.setContentHandler(handler);
            return parser;
        }
    
        /** 
         * See org.xml.sax.helpers.DefaultHandler javadocs 
         */
        private static class SheetHandler extends DefaultHandler {
            private SharedStringsTable sst;
            private String lastContents;
            private boolean nextIsString;
            
            private SheetHandler(SharedStringsTable sst) {
                this.sst = sst;
            }
            
            public void startElement(String uri, String localName, String name,
                    Attributes attributes) throws SAXException {
                // c => cell
                if(name.equals("c")) {
                    // Print the cell reference
                    System.out.print(attributes.getValue("r") + " - ");
                    // Figure out if the value is an index in the SST
                    String cellType = attributes.getValue("t");
                    if(cellType != null && cellType.equals("s")) {
                        nextIsString = true;
                    } else {
                        nextIsString = false;
                    }
                }
                // Clear contents cache
                lastContents = "";
            }
            
            public void endElement(String uri, String localName, String name)
                    throws SAXException {
                // Process the last contents as required.
                // Do now, as characters() may be called more than once
                if(nextIsString) {
                    int idx = Integer.parseInt(lastContents);
                    lastContents = new XSSFRichTextString(sst.getEntryAt(idx)).toString();
                    nextIsString = false;
                }
    
                // v => contents of a cell
                // Output after we've seen the string contents
                if(name.equals("v")) {
                    System.out.println(lastContents);
                }
            }
    
            public 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();
            System.out.println("11");
            example.processOneSheet(args[0]);
            example.processAllSheets(args[0]);
        }
    }
    复制代码

    运行的时候使用本地的文件地址替代main函数里面的参数就可以运行(亲测可以)。

    第三种方式:

    其核心是减少存储在内存当中的数据,达到一定行数就存储到硬盘的临时文件中。

    pom文件需要增加依赖:

    <dependency>
        <groupId>xerces</groupId>
        <artifactId>xercesImpl</artifactId>
        <version>2.11.0</version>
    </dependency>

    java代码如下:

    复制代码
    package excel;
    
    
    //import junit.framework.Assert;
    import java.io.FileOutputStream;
    
    import org.apache.poi.ss.usermodel.Cell;
    import org.apache.poi.ss.usermodel.Row;
    import org.apache.poi.ss.usermodel.Sheet;
    import org.apache.poi.ss.usermodel.Workbook;
    import org.apache.poi.ss.util.CellReference;
    import org.apache.poi.xssf.streaming.SXSSFWorkbook;
    
    public class SXSSFDemo {
        public static void main(String[] args) throws Throwable {
            
            SXSSFWorkbook wb = new SXSSFWorkbook(100); // 在内存当中保持 100 行 , 超过的数据放到硬盘中
            Sheet sh = wb.createSheet();
            for(int rownum = 0; rownum < 10000; rownum++){
                Row row = sh.createRow(rownum);
                for(int cellnum = 0; cellnum < 10; cellnum++){
                    Cell cell = row.createCell(cellnum);
                    String address = new CellReference(cell).formatAsString();
                    cell.setCellValue(address);
                }
    
            }     
            
            FileOutputStream out = new FileOutputStream("/Users/tootwo2/Documents/sxssf.xlsx");
            wb.write(out);
            out.close();
    
            // dispose of temporary files backing this workbook on disk
            wb.dispose();
        }
    
    }
    转载:https://www.cnblogs.com/tootwo2/p/6683143.html
    展开全文
  • 前言 poi的读取的三种模式 ... 基于事件驱动,SAX的方式解析excel,cup和内存消耗低 只读 usermodel 传统方式,cpu和内存消耗 可读可写   依赖包(3.17版本) &lt;!--...
  • POI读写大数据量excel,解决超过几万行而导致内存溢出的问题
  • poi读取大数据量excel文件,避免内存溢出,行级操作 根据本网站的资源修改的。 将一些类路径错误全部进行了修正。 另外,需要自己在类路径里,放spring-context.jar和spring-beans.jar包。
  • 前言 最近生产环境有个老项目一直内存报警,不时的还出现内存泄漏,导致需要重启服务器,已经严重影响正常服务了。 分析 1.dump内存文件 liunx使用如下命令: ? 1 ./jmap -dump:format=... 2.......
  • java 使用 poi 解析导入大数据量(几万数据量+)时,报出OOM。这是使用POI 第二种处理方法,解决大数据量导入内存溢出问题,并提升效率
  • 实际项目中经常会遇到excel导入、导出操作,数据量过大会导致内存溢出,自己封装了一个导入导出的工具类,包括用户模式、事件驱动模式两种导入导出,数据量较小是可以使用用户模式,数据量比较使用事件驱动模式,...
  • 昨天,产品提了一个紧急需求,让把十一月份已发货的商品数据导出来,写好SQL发给DBA执行之后,得到了三十多个100W数据Excel文件。有一个属性是以JSON格式存在表中一个字段里面的,需要加工Excel文件将其单独取出来...
  • https://www.cnblogs.com/wangchl/p/11400025.htmlhttps://www.cnblogs.com/swordfall/p/8298386.html#auto_id_5 用户模式只能处理小文件excel的导入导出,文件的处理要用sax模式
  • Excel中的数据量超过10万行时,在用POI读取文件流时很容易引起失败,需要引入xlsx-streamer来进行资源的打开,剩下的处理同POI处理上百行数据量类似:filePath=>FileInputStream=>Workbook=>Sheet=>...
  • 另一篇文章http://www.cnblogs.com/tootwo2/p/8120053.html... 大数据量excel一般都是.xlsx格式的,网上使用POI读写的例子比较多,但是很少提到读写非常大数据量excel的例子,POI官网上提到XSSF有三种读写exc...
  • Java解析大数据量Excel,支持解析百万行excel数据,十万数据基本上十来秒就解析完毕,亲测过最大excel1048576行数据用时219秒,硬件好点的PC估计跑起来更快。
  • java poi 解析excel数据

    2017-09-06 15:29:53
    解析excel文件数据 .xls格式;XSSF为解析.xlsx格式 public static List> analysisXlsExcel(HSSFWorkbook workbook,String[]columnsArr){ List> lstData = new LinkedList>(); HSSFFormulaEvaluator evaluator ...
  • 使用POI解析Excel

    2018-09-08 23:41:52
    Excel作为一种常用的数据存储格式,在很多项目中都会有相应的导入导出的功能。这篇文章会介绍如何使用Java操作Excel,以及如何解决文件读写时内存溢出的问题。 1、OpenXML标准 Word、Excel、PPT是Office办公...
  • 最近项目需求,有最低十万的数据导入最高500万的数据导入需求,poi,是开源对Excel支持非常强大的框架,因此研究了一番,此过程借阅网上多为人士的代码,和见解,我发现网上的代码都是那一套,是一个前辈在github上的一个...
1 2 3 4 5 ... 20
收藏数 2,572
精华内容 1,028