繁体   English   中英

检查流是否是zip文件

[英]Checking if a stream is a zip file

我们需要确定传入的InputStream是否是对zip文件或zip数据的引用。 我们没有引用流的基础源。 我们的目标是将此流的内容复制到指向备用位置的OutputStream中。

我尝试使用ZipInputStream读取流并提取ZipEntry。 如果流是常规文件,ZipEntry为null - 正如预期的那样 - 但是,在检查ZipEntry时,我从流中丢失了初始的几个字节。 因此,当我知道流是常规流时,我已经丢失了流中的初始数据。

关于如何检查InputStream是否是没有数据丢失的存档的任何想法都会有所帮助。

谢谢。

假设您的原始输入流没有缓冲,我会尝试将原始流包装在BufferedInputStream中,然后将其包装在ZipInputStream中进行检查。 您可以在检查后使用BufferedInputStream中的“mark”和“reset”返回到流中的初始位置。

这就是我做到的。

如果GZIPInputStream检测到不正确的zip格式,则使用mark / reset恢复流(抛出ZipException)。

/**
 * Wraps the input stream with GZIPInputStream if needed. 
 * @param inputStream
 * @return
 * @throws IOException
 */
private InputStream wrapIfZip(InputStream inputStream) throws IOException {
    if (!inputStream.markSupported()) {
        inputStream = new BufferedInputStream(inputStream);
    }
    inputStream.mark(1000);
    try {
        return new GZIPInputStream(inputStream);
    } catch (ZipException e) {
        inputStream.reset();
        return inputStream;
    }
}

您可以检查ZIP本地标头签名(PK 0x03 0x04)的流的第一个字节,这对于大多数情况来说已经足够了。 如果您需要更高的精度,则应该使用最后的~100个字节并检查中央目录定位器字段。

这听起来有点像黑客,但你可以实现一个代理java.io.InputStream来放在ZipInputStream和你最初传递给ZipInputStream的构造函数的流之间。 您的代理将流式传输到缓冲区,直到您知道它是否是ZIP文件。 如果没有,那么缓冲区可以节省您的一天。

您已经描述了一个java.io.PushbackInputStream - 除了read() ,它还有一个unread(byte[]) ,它允许您将它们推送到流的前面,并再次重新read()它们。

从JDK1.0开始它就在java.io (虽然我承认直到今天才看到它的使用)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM