您现在的位置是:首页 > 文章详情

Java POI重复读取excel:stream closed,回退流PushbackInputStream解决

日期:2018-09-09点击:500

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

原文链接:https://yq.aliyun.com/articles/637718
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章