Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/359.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 检查流是否为zip文件_Java_Stream_Zip - Fatal编程技术网

Java 检查流是否为zip文件

Java 检查流是否为zip文件,java,stream,zip,Java,Stream,Zip,我们需要确定传入的InputStream是对zip文件还是zip数据的引用。我们没有引用流的底层源。我们的目标是将此流的内容复制到指向备用位置的OutputStream中 我尝试使用ZipInputStream读取流并提取一个ZipEntry。如果流是一个常规文件,那么ZipEntry是空的——正如预期的那样——但是,在检查ZipEntry时,我从流中去掉了最初的几个字节。因此,当我知道流是常规流时,我已经丢失了流中的初始数据 任何关于如何检查InputStream是否是无数据丢失的存档的想法都

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

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

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


谢谢。

这听起来有点像黑客攻击,但您可以实现一个代理,位于ZipInputStream和最初传递给ZipInputStream构造函数的流之间。您的代理将流式传输到缓冲区,直到您知道它是否是ZIP文件。如果没有,则缓冲区可以节省您的时间。

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

您已经描述了a-除了
read()
,它还有一个
未读(byte[])
,这允许您将它们bck推到流的前面,并再次重新读取它们


从JDK1.0开始,它就出现在
java.io
中(尽管我承认直到今天我才看到它的用途)。

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

我就是这样做的

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


我确实尝试过使用PushbackInputStream。但是,创建ZipInputStream以检查流是否具有ZipEntry并因此成为存档的行为,除了回推流的读取之外,还会读取字节,这些字节会丢失到unread()调用中。@AKS:等等,所以不能将PBS包装到ZS中?这样做会破坏PBS的实用性:(十年后,我确认
PushbackInputStream
适用于此用例。是的,这似乎是验证流的最明显的方法。但是,我理解,根据用于创建zip的工具,标题可能会有所不同。因此,尽管是最可靠的检查,但我们从那时起就不再使用此方法了不想检查每一个可能的pkzip头。请让我知道基于工具的头是否存在差异。ZIP标准对ZIP本地头字段有一个很强的标准,因此所有ZIP存档必须具有相同的格式。我真的不知道这怎么不是正确的答案。如果可以,为什么要做这么多工作检查前4个字符?@NickolayOlshevsky,你能给我们提供一个这样验证的示例代码吗?是的,它听起来确实像一个黑客:)…但很有趣。我将尝试Galaxus的建议,如果不起作用的话,试试这个:)谢谢。我要去“呸!”。我要试试这个,这个很管用。我可以将我的原始InputStream包装为BufferedInputStream,设置一个标记,然后创建一个ZipInputStream来检查ZipEntry。一个reset()调用,我的流就可以重用了。现在,尝试缓冲区的最佳大小。多谢!请参阅下面我对Galaxus回复的评论-这是我作为决议所采取的方法。谢谢大家。欢迎来到Stack Overflow!不要忘记将您选择的答案标记为“已选定”(左侧的复选框)。
/**
 * 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;
    }
}