How can I read from a Winzip self-extracting (exe) zip file in Java?

后端 未结 4 457
面向向阳花
面向向阳花 2020-12-09 21:46

Is there an existing method or will I need to manually parse and skip the exe block before passing the data to ZipInputStream?

4条回答
  •  执念已碎
    2020-12-09 22:07

    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.

    Zip file layout

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

提交回复
热议问题