使用Apache bzip2库时出现NullPointerException

4
我正在使用Apache Ant中的BZip2压缩库。文档链接如下: http://javadoc.haefelinger.it/org.apache.ant/1.7.1/org/apache/tools/bzip2/CBZip2InputStream.html 但是在运行代码时,我一直收到以下错误提示:
   Exception in thread "main" java.lang.NullPointerException
    at org.apache.tools.bzip2.CBZip2InputStream.bsR(CBZip2InputStream.java:323)
    at org.apache.tools.bzip2.CBZip2InputStream.bsGetUChar(CBZip2InputStream.java:341)
    at org.apache.tools.bzip2.CBZip2InputStream.initBlock(CBZip2InputStream.java:230)
    at org.apache.tools.bzip2.CBZip2InputStream.<init>(CBZip2InputStream.java:178)
    at org.apache.tools.bzip2.bzipCompression.main(bzipCompression.java:37)

错误出现在第 - 行。
**CBZip2InputStream cin = new CBZip2InputStream(fileInputStream);**

我的源代码是 -

  public static void main(String[] args) throws IOException, NullPointerException {
    // TODO Auto-generated method stub

    FileReader inFile = new FileReader("alice29.txt");
    BufferedReader buff = new BufferedReader(inFile);

    FileOutputStream fout = new FileOutputStream("alicea.txt");
    fout.write("BZ".getBytes());


    CBZip2OutputStream czout = new CBZip2OutputStream (fout);

    String message = buff.readLine(); // read first line

    while(message!=null){
        byte[] input = message.getBytes();
        czout.write(input);
        message = buff.readLine();
    }
    czout.flush();
    czout.close();


    InputStream fileInputStream = new FileInputStream("alicea.txt");
    CBZip2InputStream cin = new CBZip2InputStream(fileInputStream);
    FileOutputStream decOut = new FileOutputStream("decompressedAlice.txt");


    byte[] buf = new byte[100000];
    int len;

    while((len = cin.read(buf))>0){
        decOut.write(buf, 0, len);
    }
    decOut.close();
    cin.close();

}

非常感谢您的帮助。

1
有什么阻止你在NPE(或CBZip2InputStream行323)上设置断点,以查看确切的变量 - 很可能是CBZip2InputStream的成员 - 是null?这应该给你一些线索,而不是我们猜测。 - NPE
1个回答

7

您正在打开一个 FileOutputStream,以便写入 alicea.txt 文件。

FileOutputStream fout = new FileOutputStream("alicea.txt");

在您的代码中,此OutputStream从未关闭,但在错误行中,您打开了对同一文件的FileInputStream:

InputStream fileInputStream = new FileInputStream("alicea.txt");
CBZip2InputStream cin = new CBZip2InputStream(fileInputStream);

在我看来,当你在一个文件上有一个打开的FileOutputStream时,你不能在同一个文件上打开一个InputStream。这可能是为什么你的FileInputStream为空并且抛出异常的原因。
更新: CBZip2InputStream中存在已知的错误,并且在2002年描述了解决方案(仍然可以在MarkMail找到),该错误仍然存在。您必须下载java类,而不能使用准备好的构建.jar归档文件。更改CBZip2InputStream.java的initialize()方法中以下行:
原始代码(从第213行开始):
private void initialize() {
    char magic3, magic4;
    magic3 = bsGetUChar();
    magic4 = bsGetUChar();
    if (magic3 != 'h' || magic4 < '1' || magic4 > '9') {
        bsFinishedWithStream();
        streamEnd = true;
        return;
    }
    setDecompressStructureSizes(magic4 - '0');
    computedCombinedCRC = 0;
}

将此更改为:

private void initialize() {
    char magic1, magic2; 
    char magic3, magic4; 
    magic1 = bsGetUChar(); 
    magic2 = bsGetUChar(); 
    magic3 = bsGetUChar(); 
    magic4 = bsGetUChar(); 
    if (magic1 != 'B' || magic2 != 'Z' | magic3 != 'h' || magic4 < '1' || magic4 > '9') {   
        bsFinishedWithStream();
        streamEnd = true;
        return;
    }
    setDecompressStructureSizes(magic4 - '0');
    computedCombinedCRC = 0;
}
最近更新: 我刚刚查看了Apache Ant的svn,发现trunk中的错误已经修复。但是尽管如此,仍然有很多下载包含这个错误。我也不小心下载了一个旧版本来测试你的问题。

@Erik: "当你在一个文件上有一个打开的FileOutputStream时,你不能在同一个文件上打开一个InputStream" -- 你能提供一下为什么会这样的参考资料吗? - NPE
我添加了fout.close();并将alicea.txt的权限更改为读、写和执行,但这并没有解决问题 :( - Ashish Agarwal
@aix:我会尝试为你找到一个参考。但是我从来没有在我的生活中见过这种情况。通常你从单个实例打开一个文件描述符到一个文件,而不是多个。 - Erik
@Erik - CBZip2OutputStream将压缩文件,我确实在目录中看到了一个压缩文件。压缩文件的名称是alicea.txt。在第二步中,我正在尝试解压文件并查看解压后的文件内容是否与原始文件alice29.txt的内容完全相同。我认为CBZip2InputStream应该用于解压文件。 - Ashish Agarwal
@Ashish Agarwal,如果您能接受我的答案并将其标记为解决方案(在我的答案计数器下方点击那个复选标记),那就太好了,这样其他人就可以看到问题已经得到解答了。 - Erik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接