Is there an existing method or will I need to manually parse and skip the exe block before passing the data to ZipInputStream?
解决方案
After reviewing the EXE file format and the ZIP file format and testing various options it appears the easiest solution is to just ignore any preamble up to the first zip local file header.
I wrote an input stream filter to bypass the preamble and it works perfectly:
ZipInputStream zis = new ZipInputStream(
new WinZipInputStream(
new FileInputStream("test.exe")));
while ((ze = zis.getNextEntry()) != null) {
. . .
zis.closeEntry();
}
zis.close();
WinZipInputStream.java
import java.io.FilterInputStream;
import java.io.InputStream;
import java.io.IOException;
public class WinZipInputStream extends FilterInputStream {
public static final byte[] ZIP_LOCAL = { 0x50, 0x4b, 0x03, 0x04 };
protected int ip;
protected int op;
public WinZipInputStream(InputStream is) {
super(is);
}
public int read() throws IOException {
while(ip < ZIP_LOCAL.length) {
int c = super.read();
if (c == ZIP_LOCAL[ip]) {
ip++;
}
else ip = 0;
}
if (op < ZIP_LOCAL.length)
return ZIP_LOCAL[op++];
else
return super.read();
}
public int read(byte[] b, int off, int len) throws IOException {
if (op == ZIP_LOCAL.length) return super.read(b, off, len);
int l = 0;
while (l < Math.min(len, ZIP_LOCAL.length)) {
b[l++] = (byte)read();
}
return l;
}
}