java.util.zip.ZipException: Not in GZIP format异常的产生原因及解决方法

问题:在使用GZIP压缩和解压缩时可能会出现java.util.zip.ZipException: Not in GZIP format异常。

原因:在使用GZIP进行压缩时,创建GZIPOutputStream对象时,会调用一个writeHeader方法,此方法会在输出流中写入GZIP的头信息。代码如下:

private void writeHeader() throws IOException {
        out.write(new byte[] {
                      (byte) GZIP_MAGIC,        // Magic number (short)
                      (byte)(GZIP_MAGIC >> 8),  // Magic number (short)
                      Deflater.DEFLATED,        // Compression method (CM)
                      0,                        // Flags (FLG)
                      0,                        // Modification time MTIME (int)
                      0,                        // Modification time MTIME (int)
                      0,                        // Modification time MTIME (int)
                      0,                        // Modification time MTIME (int)
                      0,                        // Extra flags (XFLG)
                      0                         // Operating system (OS)
                  });
    }

头部信息中前两个字节用于存储魔数,GZIP_MAGIC值为35615,第一个字节存储低位,第二个字节存储高位。在解压缩时GZIPInputStream会调用readheader读取头信息。代码如下:

    private int readHeader(InputStream this_in) throws IOException {
        CheckedInputStream in = new CheckedInputStream(this_in, crc);
        crc.reset();
        // Check header magic
        if (readUShort(in) != GZIP_MAGIC) {
            throw new ZipException("Not in GZIP format");
        }
        // Check compression method
        if (readUByte(in) != 8) {
            throw new ZipException("Unsupported compression method");
        }
        // Read flags
        int flg = readUByte(in);
        // Skip MTIME, XFL, and OS fields
        skipBytes(in, 6);
        int n = 2 + 2 + 6;
        // Skip optional extra field
        if ((flg & FEXTRA) == FEXTRA) {
            int m = readUShort(in);
            skipBytes(in, m);
            n += m + 2;
        }
        // Skip optional file name
        if ((flg & FNAME) == FNAME) {
            do {
                n++;
            } while (readUByte(in) != 0);
        }
        // Skip optional file comment
        if ((flg & FCOMMENT) == FCOMMENT) {
            do {
                n++;
            } while (readUByte(in) != 0);
        }
        // Check optional header CRC
        if ((flg & FHCRC) == FHCRC) {
            int v = (int)crc.getValue() & 0xffff;
            if (readUShort(in) != v) {
                throw new ZipException("Corrupt GZIP header");
            }
            n += 2;
        }
        crc.reset();
        return n;
    }

GZIPInputStream首先通过readUShort读取前两个字节然后与魔数进行比较,如果相同表示当前字节数组为GZIP格式的字节数组,如果不相同则表示当前字节数组不是GZIP格式的数组于是会抛出异常java.util.zip.ZipException: Not in GZIP format。

结论:在使用GZIP进行压缩和解压时,如果压缩后的字节数组在传输过程中发生改变就会导致此异常的发生,所以如果不是直接传输压缩后的字节数组而是字符串时,在转换为字符串时,一定要使用ISO-8859-1这样的单字节编码,否则在将字符串转换为字节数组时会导致节数组产生变化,从而产生该异常。

你可能感兴趣的:(java.util.zip.ZipException: Not in GZIP format异常的产生原因及解决方法)