您的代码不起作用的原因是 Zip LZMA 压缩数据段与普通压缩 LZMA 文件相比具有不同的标头。
您可以在以下位置阅读规格:https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT(4.4.4 通用位标志,5.8 LZMA - 方法 14),但引用重要部分:
5.8.5 [...] LZMA 压缩数据段将由 LZMA 属性标头和后跟 LZMA 压缩数据组成,如下所示:
[LZMA properties header for file 1]
[LZMA compressed data for file 1]
[...]
5.8.8 LZMA Properties Header 中属性信息的存储字段如下:
LZMA Version Information 2 bytes
LZMA Properties Size 2 bytes
LZMA Properties Data variable, defined by "LZMA Properties Size"
5.8.8.1 LZMA 版本信息 - 该字段标识用于压缩文件的 LZMA SDK 版本。第一个字节将存储 LZMA SDK 的主版本号,第二个字节将存储次版本号。
5.8.8.2 LZMA 属性大小 - 该字段定义剩余属性数据的大小。通常这个大小应该由 SDK 的版本决定。包含此大小字段是为了方便,并有助于避免将来由于此压缩算法的更改而出现任何歧义。
5.8.8.3 LZMA 属性数据 - 这个可变大小的字段记录 LZMA SDK 定义的解压缩器所需的值。存储在该字段中的数据应该使用“LZMA 版本信息”字段定义的 SDK 版本中的 WriteCoderProperties() 来获取。
代码示例:
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipFile;
import org.apache.commons.compress.archivers.zip.ZipMethod;
import org.apache.commons.io.IOUtils;
import org.tukaani.xz.LZMAInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
public class ApacheComm
{
public InputStream getInputstreamForEntry(ZipFile zipFile, ZipArchiveEntry ze) throws IOException
{
if (zipFile.canReadEntryData(ze))
{
return zipFile.getInputStream(ze);
} else if (ze.getMethod() == ZipMethod.LZMA.getCode()) {
InputStream inputStream = zipFile.getRawInputStream(ze);
ByteBuffer buffer = ByteBuffer.wrap(IOUtils.readFully(inputStream, 9))
.order(ByteOrder.LITTLE_ENDIAN);
// Lzma sdk version used to compress this data
int majorVersion = buffer.get();
int minorVersion = buffer.get();
// Byte count of the following data represent as an unsigned short.
// Should be = 5 (propByte + dictSize) in all versions
int size = buffer.getShort() & 0xffff;
if (size != 5)
throw new UnsupportedOperationException();
byte propByte = buffer.get();
// Dictionary size is an unsigned 32-bit little endian integer.
int dictSize = buffer.getInt();
long uncompressedSize;
if ((ze.getRawFlag() & (1 << 1)) != 0)
{
// If the entry uses EOS marker, use -1 to indicate
uncompressedSize = -1;
} else {
uncompressedSize = ze.getSize();
}
return new LZMAInputStream(inputStream, uncompressedSize, propByte, dictSize);
} else {
throw new UnsupportedOperationException();
}
}
}