这是我是如何做到的。
如果GZIPInputStream检测到不正确的zip格式(抛出ZipException),使用mark/reset来恢复流。
/**
* 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.PushbackInputStream - 除了read(),它还有一个unread(byte[])方法,允许您将它们推回流的前面,并重新read()它们。
它在JDK1.0中就位于java.io(尽管我承认直到今天我还没有看到过它的使用)。
PushbackInputStream 可以用于这种用例。 - bric3听起来有点像黑客,但你可以实现一个代理 java.io.InputStream 来坐在 ZipInputStream 和你最初传递给 ZipInputStream 构造函数的流之间。你的代理将流式传输到缓冲区,直到你知道它是 ZIP 文件还是其他文件。如果不是 ZIP 文件,则缓冲区会拯救你的一天。