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相关类(如POIFSFileSystem、HSSFWorkbook)处理;.xlsx(Excel 2007 及以后)基于 XML 格式,需用XSSF相关类(如XSSFWorkbook)处理。- 若用
HSSF类读取.xlsx文件(或反之),会因格式不匹配报错。
常见错误用法
手动判断文件格式并选择对应类,容易因判断逻辑错误导致兼容问题:
1 | // 错误示例:仅支持 .xls 格式,无法处理 .xlsx |
通用解决方案:使用 WorkbookFactory
POI 提供 WorkbookFactory 工具类,可自动识别文件格式并创建对应的 Workbook 实例(HSSFWorkbook 或 XSSFWorkbook),无需手动判断格式。
核心代码实现
1 | import org.apache.poi.ss.usermodel.Workbook; |
WorkbookFactory 的优势
- 自动兼容:无需判断
.xls或.xlsx,内部根据文件头信息自动选择HSSF或XSSF; - 资源安全:推荐配合 try-with-resources 语法使用,自动关闭流和 Workbook,避免资源泄露;
- 支持加密文件:可通过重载方法
WorkbookFactory.create(fis, password)读取加密的 Excel 文件(需传入密码)。
扩展:文件格式手动判断(可选)
若需手动区分格式(如特殊业务逻辑),可通过文件头或后缀判断:
通过文件头判断(更可靠)
.xls 和 .xlsx 的文件头标识不同,可读取文件前几个字节判断:
1 | /** |
通过文件后缀判断(简单但不绝对)
1 | public static boolean isXlsxBySuffix(String fileName) { |
- 注意:后缀可被手动修改(如
.xls文件改名为.xlsx),可能导致误判,推荐优先使用文件头判断。
常见问题与解决方案
1. WorkbookFactory 读取时报错 “Invalid header signature”
- 原因:文件不是有效的 Excel 格式(如伪装成
.xls的文本文件); - 解决:先校验文件格式(如通过文件头),再调用
WorkbookFactory.create()。
2. 大文件读取内存溢出
原因:
XSSFWorkbook会将整个 Excel 加载到内存,超大文件(如 10 万行数据)可能导致 OOM;解决:使用 POI 的事件驱动模式(SXSSFWorkbook或XSSFReader)处理大文件:
1 | // 处理超大 .xlsx 文件(仅加载部分行到内存) |
3. 依赖冲突导致类找不到
原因:项目中存在多个版本的 POI 依赖,或缺失
poi-ooxml依赖;解决:
确保
poi和poi-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"><<span class="name">dependency</span>></span> </span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.apache.poi<span class="tag"></<span class="name">groupId</span>></span> </span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>poi-ooxml<span class="tag"></<span class="name">artifactId</span>></span> </span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>4.1.2<span class="tag"></<span class="name">version</span>></span> </span><br><span class="line"> <span class="tag"><<span class="name">exclusions</span>></span> </span><br><span class="line"> <span class="tag"><<span class="name">exclusion</span>></span> </span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.apache.poi<span class="tag"></<span class="name">groupId</span>></span> </span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>poi<span class="tag"></<span class="name">artifactId</span>></span> </span><br><span class="line"> <span class="tag"></<span class="name">exclusion</span>></span> </span><br><span class="line"> <span class="tag"></<span class="name">exclusions</span>></span> </span><br><span class="line"><span class="tag"></<span class="name">dependency</span>></span> </span><br></pre></td></tr></table></figure>:hexoPostRenderEscape-->
v1.3.10