博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java POI重复读取excel:stream closed,回退流PushbackInputStream解决
阅读量:6217 次
发布时间:2019-06-21

本文共 3273 字,大约阅读时间需要 10 分钟。

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介绍参考:

转载地址:http://aplja.baihongyu.com/

你可能感兴趣的文章
分享SQL2005 查询表结构的SQL语句
查看>>
Android 手机如何防范吸费插件
查看>>
Copy-On-Write容器之二:CopyOnWriteArraySet
查看>>
ACCESS的分页之道,Access中实现row_number() over()聚合函数功能
查看>>
IOS成长之路-NSMutableURLRequest实现Post请求
查看>>
【Cocos2D-X 】初窥门径(9)播放音乐/音效
查看>>
HDU3930(离散对数与原根)
查看>>
茴香豆的第五种写法---设置ExpandableListView系统自带图标按下效果
查看>>
MSSQL Rebuild(重建)索引
查看>>
Linux_CentOS-服务器搭建 <七>
查看>>
转载:mysql如果数据不存在,则插入新数据,否则更新的实现方法
查看>>
<转>多线程中的lua同步问题
查看>>
转oracle 学习- 数据类型
查看>>
Eclipse安装插件支持jQuery智能提示
查看>>
cidaemon.exe进程cpu占用率高及关闭cidaemon.exe进程方法
查看>>
C语言课程设计—图书管理系统
查看>>
iOS 多线程
查看>>
【BZOJ】1096: [ZJOI2007]仓库建设(dp+斜率优化)
查看>>
SQL删除重复数据方法
查看>>
C#资源文件与与资源名称字符串之间的互相转化
查看>>