当前位置:   article > 正文

POI处理导入excel发生RecordInputStream$LeftoverDataException处理记录_org.apache.poi.hssf.record.recordinputstream$lefto

org.apache.poi.hssf.record.recordinputstream$leftoverdataexception: initiali

项目场景:

现场运维反馈,甲方爸爸有业务导入excel表单发生“系统异常”,但是不是每个人都有这种问题,个别用户导入的excel存在异常,由于网络隔离和生产日志管理原因,一直无法拿到error日志,只能请求到家里协助定位问题。

但是家里不管怎么导入excel文件就是无法复现,故怀疑是文件问题,让现场人员把业务的excel表数据拷贝到新建的excel里面试试,结果导入成功,所以只能说临时解决了问题。

通过各种申请,层层审批,终于拿到了导入出错的原始文件,开始进行分析解决问题之路。


问题描述

文件问题:拿到原始文件后,通过office打开,发现打开文件标题上出现了“兼容模式”字样,如下图:

此时可以确认文件应该是第三方应用系统中导出的文件,而非通过excel进行制作的表格数据。

导入程序报错信息:通过把此文件导入测试,发现错误很明显

  1. org.apache.poi.hssf.record.RecordInputStream$LeftoverDataException: Initialisation of record 0x31(FontRecord) left 4 bytes remaining still to be read.
  2. at org.apache.poi.hssf.record.RecordInputStream.hasNextRecord(RecordInputStream.java:188)
  3. at org.apache.poi.hssf.record.RecordFactoryInputStream.nextRecord(RecordFactoryInputStream.java:234)
  4. at org.apache.poi.hssf.record.RecordFactory.createRecords(RecordFactory.java:488)
  5. at org.apache.poi.hssf.usermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:343)
  6. at org.apache.poi.hssf.usermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:306)
  7. at org.apache.poi.hssf.usermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:258)
  8. at org.apache.poi.hssf.usermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:241)
  9. ... ...

通过异常关键字进行检索,很多解决方案都是文件另存未就能解决问题,而没有进行具体解决。本着能不改就不改的理念,让PM跟甲方爸爸进行了沟通,得到的答复是:凭什么要另存为,下载下来的数据都是都是核心数据,另存为如果改动了这个责任谁来担当,你们必须解决。好吧,都是“甩锅”。

原因分析:

通过异常报错位置,在IDEAL里面找到反编译后的代码位置,发现发生问题的位置原逻辑如下:

  1. public boolean hasNextRecord() throws LeftoverDataException {
  2. if (this._currentDataLength != -1 && this._currentDataLength != this._currentDataOffset) {
  3. throw new LeftoverDataException(this._currentSid, this.remaining());
  4. }
  5. if (this._currentDataLength != DATA_LEN_NEEDS_TO_BE_READ) {
  6. this._nextSid = this.readNextSid();
  7. }
  8. return this._nextSid != INVALID_SID_VALUE;
  9. }

此处由于 this._currentDataLength != this._currentDataOffset 导致抛出异常。

通过借鉴:NPOI.HSSF.Record.LeftoverDataException: Initialisation of record 0x31 left 4 bytes remaining still t_xue251248603的博客-CSDN博客

此篇文章中的方法,进行了处理之路。


解决方案:

很多都说需要对源码重新打包,此种做法在我们项目中是无法实施的,按照合同协议要求,第三方包,必须使用原生,不允许引用项目中的第三方包,所有包都是maven仓库中的包。所以只能选择另外的一个解决方案:重写jar包中的类,通过JVM的编译输出优先使用项目src中的类原理来实现覆盖jar包中的类的方法进行处理。

首先,新建包:org.apache.poi.hssf.record,然后新建类RecordInputStream,保持跟poi包中一致,再进行代码修改。

  1. public boolean hasNextRecord() throws LeftoverDataException {
  2. if (this._currentDataLength != -1 && this._currentDataLength != this._currentDataOffset) {
  3. // throw new LeftoverDataException(this._currentSid, this.remaining());
  4. readToEndOfRecord();
  5. }
  6. if (this._currentDataLength != DATA_LEN_NEEDS_TO_BE_READ) {
  7. this._nextSid = this.readNextSid();
  8. }
  9. return this._nextSid != INVALID_SID_VALUE;
  10. }
  11. private void readToEndOfRecord() {
  12. while (this._currentDataOffset < this._currentDataLength)
  13. readByte();
  14. }

(此处代码参考网上方法进行处理) ,再结合刚刚参考的文档说明规避“Found EOFRecord before WindowTwoRecord was encountered”异常,故还要重新建类RecordOrderer以此来覆盖poi.jar里面的此类,此类的包路径为:org.apache.poi.hssf.model。修改代码如下:

  1. public static boolean isEndOfRowBlock(int sid) {
  2. switch (sid) {
  3. case EOFRecord.sid:
  4. //为了解决其他非标准excel生成的文件进行导入
  5. // throw new RuntimeException("Found EOFRecord before WindowTwoRecord was encountered");
  6. case DrawingRecord.sid:
  7. case DrawingSelectionRecord.sid:
  8. case ObjRecord.sid:
  9. case TextObjectRecord.sid:
  10. case ColumnInfoRecord.sid: // See Bugzilla 53984
  11. case GutsRecord.sid: // see Bugzilla 50426
  12. case WindowOneRecord.sid:
  13. // should really be part of workbook stream, but some apps seem to put this before WINDOW2
  14. case WindowTwoRecord.sid:
  15. return true;
  16. case DVALRecord.sid:
  17. return true;
  18. default:
  19. return PageSettingsBlock.isComponentRecord(sid);
  20. }
  21. }

让其EOFRecord.sid的数据不抛出异常,直接注释掉。

本以为一切顺利,结果调试中出现以下异常:

  1. java.lang.RuntimeException: Unexpected record type (org.apache.poi.hssf.record.PaneRecord)
  2. at org.apache.poi.hssf.record.aggregates.RowRecordsAggregate.<init>(RowRecordsAggregate.java:97)
  3. at org.apache.poi.hssf.model.InternalSheet.<init>(InternalSheet.java:183)
  4. at org.apache.poi.hssf.model.InternalSheet.createSheet(InternalSheet.java:122)
  5. at org.apache.poi.hssf.usermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:354)
  6. at org.apache.poi.hssf.usermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:306)
  7. at org.apache.poi.hssf.usermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:258)
  8. at org.apache.poi.hssf.usermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:241)

好吧,继续处理RowRecordsAggregate类吧,还是按照覆盖模式进行处理。

修改代码如下:

  1. public RowRecordsAggregate(RecordStream rs, SharedValueManager svm) {
  2. this(svm);
  3. while(true) {
  4. while(rs.hasNext()) {
  5. Record rec = rs.getNext();
  6. switch (rec.getSid()) {
  7. case DConRefRecord.sid:
  8. this.addUnknownRecord(rec);
  9. case DBCellRecord.sid:
  10. break;
  11. case RowRecord.sid:
  12. this.insertRow((RowRecord)rec);
  13. break;
  14. default:
  15. if (rec instanceof UnknownRecord) {
  16. this.addUnknownRecord(rec);
  17. while(rs.peekNextSid() == 60) {
  18. this.addUnknownRecord(rs.getNext());
  19. }
  20. } else if (rec instanceof MulBlankRecord) {
  21. this._valuesAgg.addMultipleBlanks((MulBlankRecord)rec);
  22. } else {
  23. //此处为了解决非标excel文件导入而重新进行处理
  24. // if (!(rec instanceof CellValueRecordInterface)) {
  25. // throw new RuntimeException("Unexpected record type (" + rec.getClass().getName() + ")");
  26. // }
  27. //
  28. // this._valuesAgg.construct((CellValueRecordInterface)rec, rs, svm);
  29. if (rec instanceof CellValueRecordInterface) {
  30. this._valuesAgg.construct((CellValueRecordInterface) rec, rs, svm);
  31. }
  32. }
  33. }
  34. }
  35. return;
  36. }
  37. }

好了,现在导入提供的原始文件,终于不报错了。

PS:发现阿里的easyExcel的github上也有人遇到此问题,但是由于是底层Poi问题,所以上面建议也是修改poi.jar源码模式进行处理。使用poi.jar版本为4.1.0 ,后续升级POI还要看此三个类是有有变更,一旦变更还要跟着进行处理(o(╥﹏╥)o)。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/blog/article/detail/88877
推荐阅读
相关标签
  

闽ICP备14008679号