如何使用commons-compress判断InputStream形式的7Z压缩包是否受密码保护
7z文件加密检测实现方案(仅持有InputStream场景)
实现原理
7z格式解析需要随机访问内容,无法直接适配单向读取的普通InputStream,因此先将输入流全量读取为字节数组,封装为 Commons Compress 提供的SeekableInMemoryByteChannel(支持随机访问的内存通道),即可复用原有基于异常的加密判定逻辑。
示例代码
import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry; import org.apache.commons.compress.archivers.sevenz.SevenZFile; import org.apache.commons.compress.utils.SeekableInMemoryByteChannel; import java.io.IOException; import java.io.InputStream; public class SevenZEncryptCheckUtil { public static boolean check7zEncrypted(InputStream sevenzInputStream) throws IOException { // 1. 将输入流全量读取为字节数组 byte[] sevenzContent = sevenzInputStream.readAllBytes(); // 2. 构造内存随机访问通道,自动关闭资源 try (SeekableInMemoryByteChannel memoryChannel = new SeekableInMemoryByteChannel(sevenzContent); SevenZFile sevenZFile = new SevenZFile(memoryChannel)) { SevenZArchiveEntry entry = sevenZFile.getNextEntry(); // 空压缩包直接返回未加密 if (entry == null) { return false; } // 尝试读取内容触发解密校验 sevenZFile.read(); // 无加密相关异常抛出则视为未加密 return false; } catch (IOException e) { // 匹配无密码访问加密文件的特定异常信息 String errMsg = e.getMessage(); return errMsg != null && errMsg.contains("Cannot read encrypted files without a password"); } } }
注意事项
- JDK 9及以上才支持
InputStream.readAllBytes(),低版本JDK可以替换为org.apache.commons.io.IOUtils.toByteArray(sevenzInputStream)(需引入commons-io依赖)自行实现流到字节数组的转换。 - 若待检测的7z文件体积很大,全量读取到内存会产生较高的堆内存占用,这种场景建议先将InputStream写入本地临时文件,再用原有本地文件逻辑检测,避免OOM问题。
- 异常判断逻辑需匹配特定错误信息,避免将文件损坏、流读取失败等其他IO异常误判为加密状态。
内容的提问来源于stack exchange,提问作者user3629
相关产品推荐
相关产品推荐

