【问题标题】:Commons Compress using 7z gives Stream is not in the BZip2 format使用 7z 的 Commons Compress 使 Stream 不是 BZip2 格式
【发布时间】:2018-05-06 10:45:49
【问题描述】:

我有这个受密码保护的 7z 存档,可以单独使用 7z 正确打开和提取。但是使用下面的代码:

    byte[] PASSWORD = "secret".getBytes();
    String fileName = "r:/txt.7z";
    SevenZArchiveEntry entry;
    try (SevenZFile arch = new SevenZFile(new File(fileName), PASSWORD)) {
        while ((entry = arch.getNextEntry()) != null) {
            System.out.println(entry.getName());
        }
//      for (var e : arch.getEntries()) {
//          System.out.println(e.getName());
//      }
    }

导致此异常:

Exception in thread "main" java.io.IOException: Stream is not in the BZip2 format
  at org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream.init(BZip2CompressorInputStream.java:252)
  at org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream.<init>(BZip2CompressorInputStream.java:134)
  at org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream.<init>(BZip2CompressorInputStream.java:112)
  at org.apache.commons.compress.archivers.sevenz.Coders$BZIP2Decoder.decode(Coders.java:254)
  at org.apache.commons.compress.archivers.sevenz.Coders.addDecoder(Coders.java:79)
  at org.apache.commons.compress.archivers.sevenz.SevenZFile.buildDecoderStack(SevenZFile.java:933)
  at org.apache.commons.compress.archivers.sevenz.SevenZFile.buildDecodingStream(SevenZFile.java:909)
  at org.apache.commons.compress.archivers.sevenz.SevenZFile.getNextEntry(SevenZFile.java:222)

请注意,如果您取消注释 for 循环并注释掉 while 循环,它实际上会在存档中打印(唯一的)文件名。是getNextEntry触发了BZip2格式的异常。

我找不到任何关于这个问题的错误报告。当然,我认为这可能是密码错误,所以我将其更改为一些垃圾,以查看结果,但随后它在消息中给出了不同的异常建议,可能是密码不正确。所以,看起来密码肯定是正确的,但我无法解压缩文件。

我的类路径中还有 xz-1.8.jar (org.tukaani.xz)。

我也用SeekableByteBuffer 尝试了SevenZFile 构造函数,但弹出完全相同的异常。

有什么线索吗?

【问题讨论】:

  • 重新创建您的 7zip 文件。不符合标准格式
  • 我做不到,文件来自外部。再次,用7z工具可以正常打开。

标签: java 7zip apache-commons-compress


【解决方案1】:

这个答案的功劳应该归功于 Apache 的 Stefan Bodewig(请参阅https://issues.apache.org/jira/browse/COMPRESS-452 我在其中放置错误报告),但我也将它放在这里以防万一有人遇到同样的问题。原来,那个代表密码的字节数组应该是UTF16-LE编码的,所以真正解决问题的就是这个小sn-p:

byte[] PASSWORD = "secret".getBytes("UTF16-LE");

当然要照顾UnsupportedEncodingException。谢谢斯特凡!

【讨论】:

  • 或者更好的getBytes(StandardCharsets.UTF_16LE) 以避免拼写错误。这就是网站更新后 Compress 的示例页面要说的内容。不客气,感谢您报告问题。
猜你喜欢
  • 2023-04-08
  • 2019-10-19
  • 1970-01-01
  • 2013-01-04
  • 2013-01-05
  • 2012-11-07
  • 2013-09-04
  • 1970-01-01
  • 2015-03-25
相关资源
最近更新 更多