0%

POI读取excel报错

POI读取excel报错解决方案:兼容 xls 与 xlsx 格式

在使用 POI 读取 Excel 文件时,因文件格式(.xls.xlsx)不同常出现格式不匹配的错误。本文将详细解析错误原因,提供通用解决方案,并介绍 WorkbookFactory 的使用技巧,帮助你无缝兼容两种格式。

错误原因分析

错误信息解读

当使用 POIFSFileSystem 读取 .xlsx 文件时,会出现以下错误:

1
The supplied data appears to be in the Office 2007+ XML. You are calling the part of POI that deals with OLE2 Office Documents. You need to call a different part of POI to process this data (eg XSSF instead of HSSF)  
  • 原因:
    • .xls(Excel 2003 及以前)基于 OLE2 格式,需用 HSSF 相关类(如 POIFSFileSystemHSSFWorkbook)处理;
    • .xlsx(Excel 2007 及以后)基于 XML 格式,需用 XSSF 相关类(如 XSSFWorkbook)处理。
    • 若用 HSSF 类读取 .xlsx 文件(或反之),会因格式不匹配报错。

常见错误用法

手动判断文件格式并选择对应类,容易因判断逻辑错误导致兼容问题:

1
2
3
4
5
6
// 错误示例:仅支持 .xls 格式,无法处理 .xlsx  
if (file.getName().endsWith(".xls")) {
workbook = new HSSFWorkbook(new FileInputStream(file));
} else {
throw new RuntimeException("不支持的文件格式");
}

通用解决方案:使用 WorkbookFactory

POI 提供 WorkbookFactory 工具类,可自动识别文件格式并创建对应的 Workbook 实例(HSSFWorkbookXSSFWorkbook),无需手动判断格式。

核心代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import org.apache.poi.ss.usermodel.Workbook;  
import org.apache.poi.ss.usermodel.WorkbookFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

public class ExcelReader {

/**
* 读取 Excel 文件(兼容 .xls 和 .xlsx)
* @param file 上传的 Excel 文件
* @return Workbook 实例(HSSFWorkbook 或 XSSFWorkbook)
*/
public static Workbook readExcel(File file) {
try (FileInputStream fis = new FileInputStream(file)) {
// 自动识别格式并创建 Workbook
return WorkbookFactory.create(fis);
} catch (IOException e) {
throw new RuntimeException("读取 Excel 失败:" + e.getMessage(), e);
}
}

// 使用示例
public static void main(String[] args) {
File excelFile = new File("data.xlsx"); // 可替换为 .xls 文件
try (Workbook workbook = readExcel(excelFile)) {
// 读取工作表、行、单元格(后续操作与格式无关)
System.out.println("工作表数量:" + workbook.getNumberOfSheets());
// ... 处理逻辑 ...
}
}
}

WorkbookFactory 的优势

  • 自动兼容:无需判断 .xls.xlsx,内部根据文件头信息自动选择 HSSFXSSF
  • 资源安全:推荐配合 try-with-resources 语法使用,自动关闭流和 Workbook,避免资源泄露;
  • 支持加密文件:可通过重载方法 WorkbookFactory.create(fis, password) 读取加密的 Excel 文件(需传入密码)。

扩展:文件格式手动判断(可选)

若需手动区分格式(如特殊业务逻辑),可通过文件头或后缀判断:

通过文件头判断(更可靠)

.xls.xlsx 的文件头标识不同,可读取文件前几个字节判断:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**  
* 判断文件是否为 .xlsx 格式(基于文件头)
*/
public static boolean isXlsx(File file) {
try (FileInputStream fis = new FileInputStream(file)) {
byte[] header = new byte[4];
fis.read(header);
// .xlsx 文件头为 [80, 75, 3, 4](对应 ZIP 格式,因 .xlsx 本质是 ZIP 压缩包)
return header[0] == 80 && header[1] == 75 && header[2] == 3 && header[3] == 4;
} catch (IOException e) {
return false;
}
}

// 使用
if (isXlsx(file)) {
workbook = new XSSFWorkbook(new FileInputStream(file));
} else {
workbook = new HSSFWorkbook(new FileInputStream(file));
}

通过文件后缀判断(简单但不绝对)

1
2
3
public static boolean isXlsxBySuffix(String fileName) {  
return fileName.toLowerCase().endsWith(".xlsx");
}
  • 注意:后缀可被手动修改(如 .xls 文件改名为 .xlsx),可能导致误判,推荐优先使用文件头判断。

常见问题与解决方案

1. WorkbookFactory 读取时报错 “Invalid header signature”

  • 原因:文件不是有效的 Excel 格式(如伪装成 .xls 的文本文件);
  • 解决:先校验文件格式(如通过文件头),再调用 WorkbookFactory.create()

2. 大文件读取内存溢出

  • 原因XSSFWorkbook 会将整个 Excel 加载到内存,超大文件(如 10 万行数据)可能导致 OOM;

  • 解决:使用 POI 的事件驱动模式(SXSSFWorkbook或XSSFReader)处理大文件:

1
2
// 处理超大 .xlsx 文件(仅加载部分行到内存)  
SXSSFWorkbook sxssfWorkbook = new SXSSFWorkbook(new XSSFWorkbook(fis), 100); // 仅保留 100 行在内存

3. 依赖冲突导致类找不到

  • 原因:项目中存在多个版本的 POI 依赖,或缺失 poi-ooxml 依赖;

  • 解决

    • 确保 poipoi-ooxml 版本一致(如均为 4.1.2);

    • 排除冲突依赖:

<!--hexoPostRenderEscape:<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span>  </span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.apache.poi<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span>  </span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>poi-ooxml<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span>  </span><br><span class="line">    <span class="tag">&lt;<span class="name">version</span>&gt;</span>4.1.2<span class="tag">&lt;/<span class="name">version</span>&gt;</span>  </span><br><span class="line">    <span class="tag">&lt;<span class="name">exclusions</span>&gt;</span>  </span><br><span class="line">        <span class="tag">&lt;<span class="name">exclusion</span>&gt;</span>  </span><br><span class="line">            <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.apache.poi<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span>  </span><br><span class="line">            <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>poi<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span>  </span><br><span class="line">        <span class="tag">&lt;/<span class="name">exclusion</span>&gt;</span>  </span><br><span class="line">    <span class="tag">&lt;/<span class="name">exclusions</span>&gt;</span>  </span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span>  </span><br></pre></td></tr></table></figure>:hexoPostRenderEscape-->

欢迎关注我的其它发布渠道

表情 | 预览
快来做第一个评论的人吧~
Powered By Valine
v1.3.10