apache.poi读取.xls文件时The content of an excel record cannot exceed 8224 bytes

ops/2024/12/22 13:53:54/

目录

  • 问题描述
  • 版本
  • 定位:打印size最大的Record
  • 定位:RefSubRecord
  • 解决
  • 代码

问题描述

使用apache.poi读取.xls文件时有The content of an excel record cannot exceed 8224 bytes的报错。待读取的文件的内容也是通过apache.poi写入的,我的文件修改步骤是先删除页签然后写入页签(页签名是保持不变的),这样一次修改的结果也是符合我的预期的,但是某次程序读取文件时就出现了下面的报错,而且手动也打不开文件了。

Exception in thread "main" org.apache.poi.util.RecordFormatException: The content of an excel record cannot exceed 8224 bytesat org.apache.poi.hssf.record.RecordInputStream.nextRecord(RecordInputStream.java:222)at org.apache.poi.hssf.record.RecordFactoryInputStream.nextRecord(RecordFactoryInputStream.java:253)at org.apache.poi.hssf.record.RecordFactory.createRecords(RecordFactory.java:494)at org.apache.poi.hssf.usermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:356)at org.apache.poi.hssf.usermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:413)at org.apache.poi.hssf.usermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:394)at com.mark.learning.bug.excel.ExcelXls.addSheet(ExcelXls.java:28)at com.mark.learning.bug.excel.ExcelXls.main(ExcelXls.java:84)

在这里插入图片描述

版本

        <dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>3.17</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>3.17</version></dependency>

定位:打印size最大的Record

既然提示某一个Record超过了上限了,那我就把这个内容打印出来看看。最新定位到ExternSheetRecord 类的_list属性。

267record的size:6066
[EXTERNSHEET]numOfRefs     = 1010
refrec         #0: extBook=0 firstSheet=-1 lastSheet=-1
refrec         #1: extBook=0 firstSheet=-1 lastSheet=-1
refrec         #2: extBook=0 firstSheet=-1 lastSheet=-1
refrec         #3: extBook=0 firstSheet=-1 lastSheet=-1
refrec         #4: extBook=0 firstSheet=-1 lastSheet=-1
refrec         #5: extBook=0 firstSheet=-1 lastSheet=-1
public class ExternSheetRecord extends StandardRecord {public final static short sid = 0x0017;private final List<RefSubRecord> _list;//这里有很多的记录信息

定位:RefSubRecord

RefSubRecord记录是什么信息?什么时候进行初始化?我在构造函数打了一个断点,发现每当删除一个页签或者新增一个页签就会创建RefSubRecord页签
在这里插入图片描述
在这里插入图片描述
这里有意思的是删除页签的时候会把对应索引的记录的firstSheetIndexlastSheetIndex修改为-1。但是后面新增的从时候又尝试根据这两个变量找到对应的索引

在这里插入图片描述
在这里插入图片描述
这样就导致到了ExternSheetRecord 类的_list属性会随着程序的运行不断的增长!

解决

1.直接替换文件类型将.xls换位新版的.xlsx
2.升级版本apache.poi版本,我尝试升级为3.8版本的时候发现就没有这个问题了,原因是再3.8中删除的删除的页签的时候不会修改RefSubRecord的信息
3.17的删除逻辑
在这里插入图片描述
3.8的删除逻辑 (少了上面红框的内容)
在这里插入图片描述

代码

复现...exceed 8224 bytes报错的代码

public class ExcelTest {private static int createSheetCnt = 0;private static final String path = "C:\\Users\\Desktop\\test2.xls";public void addSheet() {try {File file = new File(path);FileInputStream in = new FileInputStream(file);HSSFWorkbook workbook = new HSSFWorkbook(in);in.close();String sheetName = "test";int sheetIndex = workbook.getSheetIndex(sheetName);if (sheetIndex >= 0) {//页签存在删除页签workbook.removeSheetAt(sheetIndex);}//新建一个页签写入文件workbook.createSheet(sheetName);FileOutputStream fileOut = new FileOutputStream(path);workbook.write(fileOut);fileOut.close();System.out.println("创建页签次数:" + ++createSheetCnt);} catch (IOException e) {throw new RuntimeException(e);}}@Testpublic void test() {for (int i = 0; i < 10000; i++) {addSheet();}}
}

打印record信息的方法

    public void printlnRecords() {try {File file = new File(path);FileInputStream in = new FileInputStream(file);HSSFWorkbook workbook = new HSSFWorkbook(in);in.close();InternalWorkbook internalWorkbook = workbook.getInternalWorkbook();List<Record> records = internalWorkbook.getRecords();System.out.println("records size:" + records.size());int maxIndex = 0;int maxRecordSize = 0;for (int i = 0; i < records.size(); i++) {Record record = records.get(i);int recordSize = record.getRecordSize();System.out.println("第" + i + "个record的size:" + recordSize);System.out.println(record);System.out.println();if (recordSize > maxRecordSize) {maxRecordSize = recordSize;maxIndex = i;}}System.out.println("第" + maxIndex + "个record的有最大size:" + maxRecordSize);} catch (IOException e) {throw new RuntimeException(e);}}

http://www.ppmy.cn/ops/125022.html

相关文章

“网络安全等级保护测评入门:基础概念与重要性“

网络安全等级保护测评&#xff08;简称“等保测评”&#xff09;是依据国家网络安全等级保护制度&#xff0c;对信息系统安全等级进行评估和评定的过程。它是提高信息系统安全性、保障信息安全的重要手段。以下是关于等保测评的基础概念与重要性的详细解读&#xff1a; 一、等…

【c++】用程序来模拟三权分立的必要性

源代码&#xff1a; #include<iostream> //立法 class legislating {int YourVar; public:legislating() {}~legislating() {}bool judge(int num){return num>10?true:false;} }; legislating s; //司法 class judicial {public:judicial() {}~judicial() {}void w…

【OceanBase诊断调优】—— 错误码 5065 和 5066 的区别

适用版本&#xff1a;V2.1.x、V2.2.x、V3.1.x、V3.2.x 5065 与 5066 是两个近似的报错。 OB_ERR_QUERY_INTERRUPTED(-5065): Message: Query execution was interrupted。 含义为执行中断, 例如终端执行 SQL 过程中按 ctrlc 终止 SQL 执行会报 -5065。 OB_ERR_SESSION_INTER…

ubuntu22.04 安装wine9.0 全网首发

wine官网推荐安装方式&#xff1a;https://gitlab.winehq.org/wine/wine/-/wikis/zh_CN/Debian-Ubuntu 博主按照这种方式是失败的&#xff0c;虽然开启了“低调上网”&#xff0c;貌似代理对于终端不起作用&#xff0c;后面会介绍替代方案&#xff0c;一样完美。 一、官网的安…

.NET 通过C#设置Excel工作表的页面设置

Excel文件数据准备就绪并需要以报告形式呈现时&#xff0c;调整Excel文件的页面设置变得尤为重要&#xff0c;不仅关乎文档的专业外观&#xff0c;还直接影响到打印或电子分享时的可读性和实用性。通过C#来自动化这一过程&#xff0c;不仅可以节省大量手动配置的时间&#xff0…

初识C语言:数据类型、运算符与表达式

目录 数据类型&#xff1a;理解信息的不同形式 数据类型转换 运算符&#xff1a;进行各种计算和操作 表达式&#xff1a;数据与运算符的结合 小结 C语言是一种广泛使用的编程语言&#xff0c;被称为"现代编程语言之母"&#xff0c;因其高效、灵活的特点而备受青…

消息队列面试题——第二篇

1. rocketmq、rabbitmq、kafka的区别 架构设计和消息模型 特性rocketmqrabbitmqkafka消息模型基于主题和消费组&#xff0c;支持发布/订阅和点对点两种模型基于队列模型&#xff0c;支持发布/订阅和点对点两种模型基于分区的主题模型&#xff0c;主要用于日志流式处理和高吞吐…

JavaScript 数组判断攻略:告别误判,精准判定变量是否为数组

引言 在 JavaScript 编程中&#xff0c;我们经常需要对不同类型的变量进行判断和处理。其中&#xff0c;判断一个变量是否是数组是一项基本且常见的任务。虽然 JavaScript 提供了多种方法来实现这个目标&#xff0c;但不同的方法各有优缺点。在本篇博客中&#xff0c;我们将介…