美文网首页
Java POI重复读取excel:stream closed,

Java POI重复读取excel:stream closed,

作者: LI木水 | 来源:发表于2018-09-10 17:30 被阅读0次

    Java POI读取Excel有两种文件格式,2003和2007以上的,需要通过不同的api进行读取,
    于是写了下面的工具类。

    public class ExcelReadUtil {
    private static Logger log = LoggerFactory.getLogger(ExcelReadKit.class);
     /**
         * 
         * @param fis
         *            输入的文件流
         * @param sheetIndex
         *            第x个sheet
         * @return
         */
        public void readExcel(InputStream fis, int sheetIndex) {
        
            try {
                Sheet sheet = null;
                Workbook wb = null;
                try {
     // 利用poi读取excel文件流,2003版本
                    POIFSFileSystem fs = new POIFSFileSystem(fis);
                    wb = new HSSFWorkbook(fs); // 读取excel工作簿
                    sheet = wb.getSheetAt(sheetIndex); // 读取excel的sheet,0表示读取第一个
                } catch (Exception e) {
     // 利用poi读取excel文件流,2007及以上版本
                    wb = new XSSFWorkbook(fis); // 读取excel工作簿
                    sheet = wb.getSheetAt(sheetIndex); // 读取excel的sheet,0表示读取第一个
                }
    
    //读取操作省略。。。
    
                wb.cloneSheet(sheetIndex);
                fis.close();
            } catch (Exception e) {
                log.error("读取Excel文件流时出错:", e);
            } finally {
                if (fis != null) {
                    try {
                        fis.close();
                    } catch (Exception e) {
                    }
                }
            }
        }
    }
    

    先读取2003(.xls)版本的,如果异常就读取2007(.xlsx)版本的,看起来没什么问题,但是实际使用中,当读取xlsx文件的时候会stream closed报错,这是为什么呢?原来当读取了一次文件流的异常之后,运行到wb = new XSSFWorkbook(fis); // 读取excel工作簿的时候,输入流已经被关闭了。
    怎么解决这个InputStream被关闭的问题呢?使用前用PushbackInputStream包装,读取前先POIFSFileSystem.hasPOIFSHeaderPOIFSFileSystem.hasPOIFSHeader方法读取流的头判断文件格式

    修改如下:

    public class ExcelReadUtil {
    private static Logger log = LoggerFactory.getLogger(ExcelReadKit.class);
     /**
         * 
         * @param fis
         *            输入的文件流
         * @param sheetIndex
         *            第x个sheet
         * @return
         */
        public void readExcel(InputStream fis, int sheetIndex) {
        
            try {
                 Sheet sheet = null;
                Workbook wb = null;
                // 不加报错:java.io.IOException: mark/reset not supported
                //PushbackInputStream参考:https://my.oschina.net/fhd/blog/345011
                if (!fis.markSupported()) {
                    fis = new PushbackInputStream(fis, 8);
                }
                /**
                 * 只能通过这种方式判断版本,使用如果通过
                 * try catch捕获异常方式先读取了一次,流会被关闭,后面就读取不到了
                 */
                //2003版
                if (POIFSFileSystem.hasPOIFSHeader(fis)) {
                    // 读取excel工作簿
                    wb = new HSSFWorkbook(fis);
                }
                //2007版
                else if (POIXMLDocument.hasOOXMLHeader(fis)) {
                    //OPCPackage.open(fis)取得一个文件的读写权限
                    wb = new XSSFWorkbook(OPCPackage.open(fis));
                }
    
    //读取操作省略。。。
    
                wb.cloneSheet(sheetIndex);
                fis.close();
            } catch (Exception e) {
                log.error("读取Excel文件流时出错:", e);
            } finally {
                if (fis != null) {
                    try {
                        fis.close();
                    } catch (Exception e) {
                    }
                }
            }
        }
    }
    

    使用工具类,此时读取两种格式的文件都没有问题了

    public class ExcelReaderTest {
    
        @Test
        public void readData() throws IOException, ParseException {
    
            File file = new File("D:\\test.xlsx");
            ExcelReadUtil excelReader = new ExcelReadUtil();
            //只读取第一个sheet页
            excelReader.readExcel(new FileInputStream(file), 0);
    //...
        }
    }
    

    具体PushbackInputStream介绍参考:https://my.oschina.net/fhd/blog/345011

    相关文章

      网友评论

          本文标题:Java POI重复读取excel:stream closed,

          本文链接:https://www.haomeiwen.com/subject/iyasgftx.html