检查流是否是zip文件

时间:2010-11-10 20:54:04

标签: java stream zip

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

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

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

感谢。

5 个答案:

答案 0 :(得分:6)

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

答案 1 :(得分:3)

这就是我做到的。

如果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;
    }
}

答案 2 :(得分:2)

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

答案 3 :(得分:0)

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

答案 4 :(得分:0)

您已经描述过java.io.PushbackInputStream - 除了read()之外,它还有一个unread(byte[]),允许您将它们推送到流的前面,并重新{{1}他们又来了。

自JDK1.0以来它位于read()(虽然我承认直到今天我还没有看到它的使用)。