Java异常之RecordInputStream$LeftoverDataException:原因、排查与修复方法

帅旋
帅旋
关注
充电
发布于 2025-06-20 | 更新于 2025-06-20

1、RecordInputStream$LeftoverDataException是什么异常?

最近在一个项目中使用 Apache POI 的 HSSF 模型读取 .xls 文件进行Excel解析时,用户上传的一个文件触发了如下Java异常:

1
2
org.apache.poi.hssf.record.RecordInputStream$LeftoverDataException: 
Initialisation of record 0x31(FontRecord) left 4 bytes remaining still to be read.

这里发现 FontRecord(ID=0x31)像是和字体有关。

经过网上搜索,发现也有人在解析 SelectionRecordNumberRecord 时遭遇类似的“剩余字节”异常,例如 record ID 0x85 出现剩余 18 字节抛出同样异常。

参考: stackoverflow.com[1]

此外还有报告出现 NumberRecord(ID=0x203)剩余 4 字节的情况,均触发 RecordInputStream$LeftoverDataException,参考: github.com[2]

2、为什么会触发RecordInputStream$LeftoverDataException?

2.1 异常原理

查看Apache POI的doc文档,可以发现,Apache POI在读取 BIFF 记录时会根据记录头中的长度精确消费字节,若读取后流中仍有未读字节,则触发 RecordInputStream$LeftoverDataException[3]

HSSF 的 RecordInputStream.hasNextRecord() 会校验是否有剩余字节,并在发现不匹配时通过抛出此异常保护后续记录解析[4]

2.2 触发场景

部分第三方工具或系统导出的 Excel 文件在写入 FontRecord 或其他记录时插入了“扩展”字节数据,导致 Apache POI 无法识别[5]

如何解决问题呢?其实很简单,手动用 Microsoft Excel 或 WPS 打开并“另存为”后,通常可清除不兼容的扩展数据,从而避免该Java异常。

2.3 官方Bug修复进度如何?

Apache Bugzilla 中的 Bug 68854 专门报告了 FontRecord 剩余 4 字节的问题,并被标记为重复 Bug 60833。[6]

Bug 60833 自 2017 年以来一直未在官方版本中彻底修复,社区仍在讨论该边缘场景的处理方案。

3、如何解决RecordInputStream$LeftoverDataException问题?

3.1 另存为 Excel

最简单的方式是手动或脚本化地使用 Excel/WPS 对 .xls 文件执行“另存为”操作,该过程会重写文件结构并剔除多余字节,从而避免此Java异常[7]

3.2 转为 .xlsx

.xls 文件转换为 Office Open XML(.xlsx)格式,使用 XSSF 解析器可绕开 BIFF 的二进制校验机制,从而彻底规避该问题。

3.3 升级或打补丁

当然,更进一步的是等待官方修复了。如果等不及,可以自己动手在本地对 Apache POI 源码中的 FontRecord.readFieldsRecordInputStream.hasNextRecord 增加容错逻辑,捕获并忽略多余字节,从而避免在Excel解析时触发RecordInputStream$LeftoverDataException异常。

Refenceces


  1. [How to resolve InputStream LeftoverDataException : Initialisation of record 0x85 left 18 bytes remaining still to be read](https://stackoverflow.com/questions/50909356/how-to-resolve-inputstream-leftoverdataexception-initialisation-of-record-0x85) ↩︎

  2. LeftoverDataException on reading xls file with HSSFWorkbook ↩︎

  3. Class RecordInputStream.LeftoverDataException ↩︎

  4. Class RecordInputStream ↩︎

  5. org.apache.poi.hssf.record.RecordInputStream$LeftoverDataException: Initialisation of record 0x31(FontRecord) left 4 bytes remaining still to be read. ↩︎

  6. [Bug 60833] Initialisation of record 0x31 left 4 bytes remaining still to be read. ↩︎

  7. POI处理导入excel发生RecordInputStream$LeftoverDataException处理记录 ↩︎

本文作者: 帅旋

本文链接: https://www.itzhai.com/columns/exception/java/java-exception-recordinputstream-leftoverdataexception-causes-troubleshooting-and-fixes.html

版权声明: 版权归作者所有,未经许可不得转载,侵权必究!联系作者请加公众号。

×
IT宅

关注公众号及时获取网站内容更新。

请帅旋喝一杯咖啡

咖啡=电量,给帅旋充杯咖啡,他会满电写代码!

IT宅

关注公众号及时获取网站内容更新。