LeftoverDataException,依赖包,apache license 2.0
1. poi3.9 LeftoverDataException
org.apache.poi.hssf.record.RecordInputStream$LeftoverDataException: Initialisation of record 0x1D left 1 bytes remaining still to be read.
at org.apache.poi.hssf.record.RecordInputStream.hasNextRecord(RecordInputStream.java:156)
at org.apache.poi.hssf.record.RecordFactoryInputStream.nextRecord(RecordFactoryInputStream.java:231)
at org.apache.poi.hssf.record.RecordFactory.createRecords(RecordFactory.java:443)
...
以前的随笔也提到过解决办法http://www.cnblogs.com/starRebel/p/5067026.html。
但是最近在优化读写excel部分的代码,发现上述方法有个缺点就是如果excel有多个sheet,那么转成csv之后只能保留其中的一个sheet,这对于通用性是个很大的缺陷。
但是excel和wps都能正确打开,所以继续搜索可能的办法。先试了试最新的3.15和3.16beta版本,仍然有这个问题。
接着在https://bz.apache.org/bugzilla/show_bug.cgi?id=47251看到了歪果仁讨论这个Exception。
What I have done for the moment is modify the hasNextRecord() method of the RecordInputStream class, so that it simply skips extra data bytes instead of throwing an exception.
But perhaps an experienced POI developer will have a better idea.
看来修改源代码是个可行的方案。定位到抛异常的地方,
public boolean hasNextRecord() throws LeftoverDataException {
if (_currentDataLength != -1 && _currentDataLength != _currentDataOffset) {
throw new LeftoverDataException(_currentSid, remaining());
}
if (_currentDataLength != DATA_LEN_NEEDS_TO_BE_READ) {
_nextSid = readNextSid();
}
return _nextSid != INVALID_SID_VALUE;
}
打算先修改源码试试,注释掉抛出异常的地方
public boolean hasNextRecord() throws LeftoverDataException {
if (_currentDataLength != -1 && _currentDataLength != _currentDataOffset) {
// throw new LeftoverDataException(_currentSid, remaining());
}
if (_currentDataLength != DATA_LEN_NEEDS_TO_BE_READ) {
_nextSid = readNextSid();
}
return _nextSid != INVALID_SID_VALUE;
}
2. 重新打包
使用的IDE是intelliJ idea community 2016.1版本。以前打包都是通过maven依葫芦画瓢的完成,但是这次下载的poi-3.9-sources.jar文件里没有pom,按照https://search.maven.org上的pom文件没折腾成功,所以打算使用IDE原始的方式。
先获取到poi-3.9依赖的包,我的做法是通过maven获取,先创建一个新的maven工程,然后替换pom文件内容为https://search.maven.org/remotecontent?filepath=org/apache/poi/poi/3.9/poi-3.9.pom的内容,这时maven会自动下载好依赖,以及依赖的依赖。以下就是poi-3.9所有的依赖。

有了这些依赖包之后,回到修改源代码的工程,先在工程目录下建立一个libs文件夹,再从maven本地仓库中把上图的依赖包复制到libs文件夹中(所有依赖包都复制到libs目录下是为了方便管理和查看)。

在“Project Structure”设置中,导入依赖包,图中modifySource是工程名,libs是新建的放置依赖包的目录

再把poi的原代码拷贝到工程中,

这时在IDE中就能看到工程目前的结构

接下来就要开始编译了,进入“Project Structure”设置,选择“Artifacts”选项,新建

点击“OK”之后,出现下图

当时也没考虑太多,只想着不想要依赖包的内容,所以把依赖包的代码都去掉了

点击确定之后,再“Build”->“Build Artifacts”,会生成一个新的包,改名字为“poi-modified.jar”。
因为这是本地修改的,所以使用“poi-modified.jar”时就不能通过maven了,需要使用IDE导入包。过程和上面提到过的一样(是否需要导入此修改包的依赖包,后面会提到),这时再运行处理excel程序,就没有报错。
在查看源代码,会发现
public boolean hasNextRecord() throws RecordInputStream.LeftoverDataException {
if(this._currentDataLength != -1 && this._currentDataLength != this._currentDataOffset) {
;
}
if(this._currentDataLength != -1) {
this._nextSid = this.readNextSid();
}
return this._nextSid != -1;
}
添加注释的哪一行已经没有了,估计是被编译器优化了。
但是,以上对源程序作出的修改很有可能导致别的问题,但是针对目前的问题,是可以这么做的。
--->插曲:重新编译之后,测试时还是报了一个错:“resource 'functionMetadata.txt' not found”。搜索一番之后,发现是在ss\formula\function路径下缺少了functionMetadata.txt文件(https://bz.apache.org/bugzilla/show_bug.cgi?id=51534)。
这才发现,网上的poi-3.9源代码编译出来,比起poi-3.9.jar包还是会缺少一些文件。那就采用缺什么补什么的办法,把functionMetadata.txt文件加到路径下,再编译测试,通过。
3. 依赖,编译
重新思考了一遍流程之后,发现一个问题:因为我在构建“poi-modified.jar”的时候并没有把依赖包放进去,并且在“poi-modified.jar”中也没有看到依赖包的代码,那么如果我在使用“poi-modified.jar”的函数时候间接调用了依赖包中的函数,会不会失败?
有了这个疑惑之后,打算做一个小的测试检测一下。
a.新建一个工程,如下图

有两个静态函数,一个使用了poi功能,一个没有。
1. 测试不包含依赖包情况:即构建的时候不包含依赖包的源码,构建a中的项目,取名“testDependency.jar”。
然后再创建另一个工程使用“testDependency.jar”包:

Main.main(null)函数创建了Workbook类,而“testDependency.jar”并没有包含poi包,所以报错如下:
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/poi/hssf/usermodel/HSSFWorkbook
at Main.main(Main.java:10)
at SMain.main(SMain.java:6)
Caused by: java.lang.ClassNotFoundException: org.apache.poi.hssf.usermodel.HSSFWorkbook
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 2 more
说明并没有找到poi的信息。
而如果调用succ()函数,则不报错正常执行。
public class SMain {
public static void main(String[] args) {
Main.succ();
}
}
b. 如果“testDependency.jar”构建时包含poi包代码,则以上两个函数都能正确执行。
综上,感觉就有点奇怪了,似乎java的编译过程和linux下c文件的编译链接过程不一样,有点动态链接的味道?
谷歌搜索一下,结合http://www.360doc.com/content/14/0218/23/9440338_353675002.shtml还有https://www.zhihu.com/question/29125656两篇内容,大致分析如下:
a). 编译时需要依赖包的文件,如果依赖包是已经编译好的.class文件,则直接引用。
b). java使用到类的时候才会加载类,不使用,则不会加载,默认从引用的包中加载。
所以,构建“testDependency.jar”时必须要有poi源文件。而使用“testDependency.jar”时,因为已经是编译好的,所以会直接引用,而不会再次编译。而调用Main.succ()函数,因为没有涉及到poi类,所以不会报错。同样的,如果excel处理程序没有用到依赖的类中的函数或类,也不会有问题,但是建议最好把依赖包都加上。
4. 如果仍然想要使用maven帮助下载依赖包,会有一个问题:


poi-ooxml-3.9依赖包中含有poi-3.9,所以maven会下载poi-3.9。“poi-3.9”和“poi-3.9-modified”含有同包同名的类,那么编译的时候会使用哪个jar包呢?如果使用“poi-3.9-modified”,那么符合我们的期望。但是如果使用“poi-3.9”,则我们做的修改就没有用了。
在IntelliJ中,可以指定加载顺序:

如上图,加载顺序从上到下,哪个jar包在前面就会优先选择这个jar包。
5. apache license
最后,在poi-3.9-sources.jar包META-INF目录下看到了License文件

正好结合上一篇随笔,实践一下开源协议。
poi使用的是apache2.0协议,约束之一是
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
也就是说,如果修改了文件,需要在被修改的文件中说明。这个一时半会也不知道怎么说明比较好,继续谷歌之,找到一个http://softwareengineering.stackexchange.com/questions/220068/file-with-apache-2-0-and-my-modifications。
有个回答说一了个方法:
You must make it clear the the file has been changed. The easiest way is to simply add your copyright after the original ones: Modifications copyright (C) 2013 <your company/name> If you did the modifications on behalf of your company, then that is in most cases also the name that you must put on the copyright notice
在没有更好说明的情况下打算采取这个形式,修改了RecordInputStream.java文件,在文件头加上:
/* ====================================================================
Modifications copyright 2016 Simba
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
either express or implied. See the License for the specific language governing
permissions and limitations under the License.
==================================================================== */
在“poi-3.9-sources.jar”的LICENSE文件(也就是apache 2.0协议)中也有如下一段话
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
正好目录下有一个NOTICE文件,依葫芦画瓢,添加一段。
此处相当于这个包是使用apache license 2.0版本了:),如果使用别的协议还要另外再研究研究。
Simba POI
Copyright 2016 Simba This product were originally based on Apache POI
Copyright 2009 The Apache Software Foundation This product includes software developed by
The Apache Software Foundation (http://www.apache.org/). This product contains the DOM4J library (http://www.dom4j.org).
Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. This product contains parts that were originally based on software from BEA.
Copyright (c) 2000-2003, BEA Systems, <http://www.bea.com/>. This product contains W3C XML Schema documents. Copyright 2001-2003 (c)
World Wide Web Consortium (Massachusetts Institute of Technology, European
Research Consortium for Informatics and Mathematics, Keio University) This product contains the Piccolo XML Parser for Java
(http://piccolo.sourceforge.net/). Copyright 2002 Yuval Oren. This product contains the chunks_parse_cmds.tbl file from the vsdump program.
Copyright (C) 2006-2007 Valek Filippov (frob@df.ru)
其实也不知道写的对不对,先这么弄着,等哪天了解的更上一层楼的时候再回来看看也不迟。
然后把这些文件打包到新构建的“testDependency.jar”中。
另外,“poi-3.9-sources.jar”使用许多小组件,如果小组件的开源协议不同,在LICENSE文件里面也包含了不同的协议说明:
APACHE POI SUBCOMPONENTS: Apache POI includes subcomponents with separate copyright notices and
license terms. Your use of these subcomponents is subject to the terms
and conditions of the following licenses: Office Open XML schemas (ooxml-schemas-1.1.jar) The Office Open XML schema definitions used by Apache POI are
a part of the Office Open XML ECMA Specification (ECMA-376, [1]).
As defined in section 9.4 of the ECMA bylaws [2], this specification
is available to all interested parties without restriction:
.......
.......
总之,先这样了,只能理解到这一步。以后再慢慢加深理解。
LeftoverDataException,依赖包,apache license 2.0的更多相关文章
- 不仅开源,而且对企业应用完全免费!ExtAspNet弃用GPL v2,拥抱Apache License 2.0(转)
不仅开源,而且对企业应用完全免费!ExtAspNet弃用GPL v2,拥抱Apache License 2.0(转) 提出问题 ExtAspNet开源以来,一直坚持开源免费的原则,但是其GPL v2的 ...
- 如何理解Apache License, Version 2.0(整理)
如何理解Apache License, Version 2.0(整理) 问题: 最近看到apache发布了2.0版本的License.而且微软也以此发布了部分源代码.我对OpenSource不是特熟, ...
- Core 2.0 的dll实时更新、https、依赖包变更问题及解决
今天所有开发环境已经迁移到mac OS下的Visual Studio Code + 命令行编译发布,而运行服务器是CentOS7,和windows没什么关联了. 只要你Relese编译并在本地有一个与 ...
- 解决org.apache.rat:apache-rat-plugin:0.8:check (default) on project hbase: Too many unapproved license
maven打包的时候报错: 报错信息: [ERROR] Failed to execute goal org.apache.rat:apache-rat-plugin:0.8:check (defau ...
- spring-framework-3.0.2RELEASE之后为啥没有依赖包了?
缘起:莫莫接到新任务要学习spring mvc,于是在网上找了个demo文档跟着一起做.这个是学习的网址: http://www.open-open.com/doc/view/a6462d9a2e2b ...
- 如何编译Apache Hadoop2.6.0源代码
如何编译Apache Hadoop2.6.0源代码 1.安装CentOS 我使用的是CentOS6.5,下载地址是http://mirror.neu.edu.cn/centos/6.5/isos/x8 ...
- 编译安装php 5.5 缺少依赖包 及解决方案
必要时可以用 YUM 选择安装以下相关软件包: #yum install gcc gcc-c++ autoconf libjpeg libjpeg-devel libpng libpng-devel ...
- Apache Spark1.1.0部署与开发环境搭建
Spark是Apache公司推出的一种基于Hadoop Distributed File System(HDFS)的并行计算架构.与MapReduce不同,Spark并不局限于编写map和reduce ...
- Pyspark spark-submit 集群提交任务以及引入虚拟环境依赖包攻略
网上提交 scala spark 任务的攻略非常多,官方文档其实也非常详细仔细的介绍了 spark-submit 的用法.但是对于 python 的提交提及得非常少,能查阅到的资料非常少导致是有非常多 ...
随机推荐
- jquery ajax 传数据到后台乱码的处理方法
前台页面先对中文进行编码,如下红色字体: function saveCommentTemplate() { $.ajax({ cache : false, type:'get', dataType:' ...
- delphi -----获取计算IP
function GetHostName:String; var ComputerName: ..MAX_COMPUTERNAME_LENGTH+] of char; Size: Cardinal; ...
- 为Visual SVN使用签名后的域名证书
装了个VisualSVN Server管理代码,可每次浏览的时候都会提示证书有问题,要不要继续神马的,好烦人,于是搜索了一下免费SSL证书,申请了一个,虽然不是绿的,但总算是不报问题了. 下面是整个过 ...
- Scala 常用语法
Clojure首先是FP, 但是由于基于JVM, 所以不得已需要做出一些妥协, 包含一些OO的编程方式 Scala首先是OO, Java语法过于冗余, 一种比较平庸的语言, Scala首先做的是简化, ...
- pycharm调试scrapy
pycharm调试scrapy 创建一个run.py文件作为调试入口 run.py中,name是要调试的爬虫的名字(注意,是爬虫类中的name,而不是爬虫类所在文件的名字) 拼接爬虫运行的命令,然后用 ...
- 流畅的python 使用一等函数实现设计模式
案例分析:重构“策略”模式 经典的“策略”模式 电商领域有个功能明显可以使用“策略”模式,即根据客户的属性或订单中的商品计算折扣.假如一个网店制定了下述折扣规则. 有 1000 或以上积分的顾客,每个 ...
- <context-param>与<init-param>的差别与作用
<context-param>的作用: web.xml的配置中<context-param>配置作用 1. 启动一个WEB项目的时候,容器(如:Tomcat)会去读它的配置文件 ...
- 利用Docker快速部署Oracle环境
工作中需要频繁使用Oracle环境,但是每次搭建起来比较消耗时间,本想通过虚拟机模板的方式来快速安装oracle vm,但是每次改ip等环境也很耗时,因此想到docker中有没有已经做好的images ...
- Delphi 正则表达式语法(7): 匹配转义字符
Delphi 正则表达式语法(7): 匹配转义字符 // ? 号的意义是匹配 0-1 次, 如果需要匹配 ? 怎么办 var reg: TPerlRegEx; begin reg := TPe ...
- [笔记] Ubuntu下编译ffmpeg+openh264+x264
[下载代码] - ffmpeg: git clone git://source.ffmpeg.org/ffmpeg.git - openh264: git clone https://github ...