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);
//...
具体PushbackInputStream介绍参考:https://my.oschina.net/fhd/blog/345011
Apache POI 实现用Java操作Excel完成读写操作
Apache POI是一个用于操作Microsoft Office格式文件(包括xls、docx、xlsx、pptx等)的Java API库。POI全称为Poor Obfuscation Implementation,是Apache Software Foundation的一个开源项目。它提供了一组Java API,使得Java程序可以读取、写入和操作Microsoft Office格式文件。
Java 导入20万数据 Mybatis和Excel 处理
最近在处理导入数据需求,原来的数据是几千行导入,一般的代码可满足。但是在导入数据进却发现一个excel有20几万数据,各种问题就出来了,首先是数据库会撑爆,因excel读入的数据太多内存也会溢出。
Java http Post下载Excel文件 xxx.xlsx 失败解决,及传输文件类型ContentType对应关系
查询数据库生成Excel下载功能。本来很简单的功能却搞了挺久的,主要因为下载的文件打不开,且此功能已是基本功能。这里记录下来方便后面查阅。
ContentType对应的文件关系查看下面连接
https://www.runoob.com/http/mime-types.html