java io 重复读文件_Java POI重复读取excel:stream closed,回退流PushbackInputStream解决...

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.hasPOIFSHeader和POIFSFileSystem.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);

//...

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值