LeftoverDataException,依赖包,apache license 2.0

摘要:
Id=47251我看到了伟瑞讨论的例外情况。我目前所做的是修改RecordInputStream类的NextRecord()方法,使其简单地跳过transabytes而不是抛出异常。但如果POI开发人员有经验,则会更好。看来修改源代码是一个可行的解决方案。找到引发异常的位置,PublicpooeanhasNextRecord()throwsLeftoverDataException{if(_currentDataLength!=INVALID_SID_VALUE;}我计划首先修改源代码,并注释掉引发异常的地方PublicpooleanhhasNextRccord()thowsLeftoverData exception{if(_currentData Length!=INVALID_SID-VALUE;}2。用于重新打包的IDE是intelliJidacommunity版本2016.1。首先获取依赖于poi-3.9的包。我的方法是通过maven。首先创建一个新的maven项目,然后用https://search.maven.org/remotecontent?filepath=org/apache/poi/poi/3.9/poi -3.9. com,Maven将自动下载依赖项和依赖项。查看源代码后,您会发现publicpool中有NextRecord()throwsRecordInputStream。如果ssformulafunction路径(https://bz.apache.org/bugzilla/show_bug.cgi?

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所有的依赖。

LeftoverDataException,依赖包,apache license 2.0第1张

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

LeftoverDataException,依赖包,apache license 2.0第2张

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

LeftoverDataException,依赖包,apache license 2.0第3张

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

LeftoverDataException,依赖包,apache license 2.0第4张

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

LeftoverDataException,依赖包,apache license 2.0第5张

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

 LeftoverDataException,依赖包,apache license 2.0第6张

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

LeftoverDataException,依赖包,apache license 2.0第7张

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

LeftoverDataException,依赖包,apache license 2.0第8张

点击确定之后,再“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”。搜索一番之后,发现是在ssformulafunction路径下缺少了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.新建一个工程,如下图

LeftoverDataException,依赖包,apache license 2.0第9张

有两个静态函数,一个使用了poi功能,一个没有。

1. 测试不包含依赖包情况:即构建的时候不包含依赖包的源码,构建a中的项目,取名“testDependency.jar”。

然后再创建另一个工程使用“testDependency.jar”包:

LeftoverDataException,依赖包,apache license 2.0第10张

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帮助下载依赖包,会有一个问题:

LeftoverDataException,依赖包,apache license 2.0第11张

LeftoverDataException,依赖包,apache license 2.0第12张

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中,可以指定加载顺序:

LeftoverDataException,依赖包,apache license 2.0第13张

如上图,加载顺序从上到下,哪个jar包在前面就会优先选择这个jar包。

5. apache license

最后,在poi-3.9-sources.jar包META-INF目录下看到了License文件

LeftoverDataException,依赖包,apache license 2.0第14张

正好结合上一篇随笔,实践一下开源协议。

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》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇chkconfig 添加脚本开机自启动vmware uos挂载windows共享目录下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

在Azure DevOps Server (TFS)的流水线中编译和测试Xcode移动应用(iPhone)

概述 Xcode是开发基于苹果macOS系统的桌面应用和移动应用的主要IDE工具。使用Azure DevOps Server (原名TFS)系统中的pipelines流水线功能,可以方便的集成Xcode项目,使用web浏览器在DevOps服务器上,实现一键编译、测试和发布等工作,省却测试发布过程中复杂的流程,大幅提高测试发布的效率,提高开发和测试团队之间的...

linux下crontab的使用方法

<spanstyle="font-size:14px;">在Linux中任务可以被配置在指定的时间段、指定的日期、或系统平均载量低于指定的数量时自动运行。 crontab是一个很方便的在unix/linux系统上定时(循环)执行某个任务的程序。 cron服务是可以根据时间、日期、月份、星期的组合来调度对重复任务执行的守护进程。linux的cr...

虹软人脸识别——官方 Qt Demo 移植到 Linux

一、前言 最近需要在 Linux 平台下开发一个人脸识别相关的应用,用到了虹软的人脸识别 SDK。之前在 Windows 平台用过,感觉不错,SDK 里面还带了 Demo 可以快速看到效果。打开 Linux 版本的 SDK 里面没有发现 Demo,于是想着把 Windows 的 Demo 移植到 Linux。这篇文章记录了移植的过程,Linux 用的是 U...

UNIX中CC编译器

大多数UNIX系统中,C编译器被称为cc用法举例:1, cc program.c -- 编译并链接一个完全包含于一个源文件的C程序。该命令产生一个称为a.out的可执行程序。中间会产生一个名为program.o的目标文件,但在链接过程完成后会被删除。 2, cc main.c sort.c other.c -- 编译并链接几个C源文件当编译的源文件超过一个...

apache maven安装教程

 一、准备工作 a.  安装jdk1.7以上版本 b. 下载maven安装包   官方下载地址:http://maven.apache.org/download.cgi       百度网盘下载地址: https://pan.baidu.com/s/1EI2CytxsnelXfZ-XFYSizA   (maven3.3.3) 二、解压Maven安装包  解...

DevOps专题|Lua引擎打造超轻量级客户端

Lua 作为一门轻量级脚本语言,源码使用标准C语言发布,语法简洁,非常适合嵌入式、客户端、游戏等场景。 Lua引擎语言特点 轻量级 源码简单,以lua最新版5.3.5为例,加上lua自身提供的lib库,仅30多个.c文件,编译后仅200多k,strip后经upx压缩,可控制在100k以下。 语法简洁 小巧灵活,支持闭包,有GC机制,通过语法糖可实现面向对...