在最终块中断 zip 中复制 ByteStream 后关闭 GZIPOutputStream

Closing GZIPOutputStream after ByteStream copy in finally block break zip

我有压缩和解压缩文本的代码。我遇到了奇怪的行为——只有当我在某个地方关闭 GZIPOutputStream 时,代码才有效,但是当我尝试将 GZIPOutputStream close 放在 finally 块中时,它会中断并且不起作用。如果将 : gzipoutputstream.close() 放在放置注释的 czip 函数中,它将起作用。但是,如果您只将它保留在 finally 块中,它就会中断。为什么?

ByteStreams.copy 函数来自 com.google.common.io guava

public class Main {

    public static byte[] dzip(byte[] s) throws IOException {
        ByteArrayInputStream sStream = null;
        ByteArrayOutputStream oStream = null;
        InputStream gzipoutputStream = null;
        ByteBuffer arrReturn = null;
        try {
            sStream = new ByteArrayInputStream(s);
            oStream = new ByteArrayOutputStream();
            gzipoutputStream = new GZIPInputStream(sStream, 1024);
            ByteStreams.copy(gzipoutputStream, oStream);
            arrReturn = ByteBuffer.wrap(oStream.toByteArray());
        }
        catch (Exception e) {
            return null;
        } finally {
            if (gzipoutputStream != null) {
                gzipoutputStream.close();
            }
            if (oStream != null) {
                oStream.close();
            }
            if (sStream != null) {
                sStream.close();
            }

        }
        return arrReturn.array();
    }
    public static byte[] czip(byte[] s) throws IOException {

        ByteArrayInputStream sStream =null;
        ByteArrayOutputStream oStream =null;
        OutputStream gzipoutputstream = null;
        byte[] returnValue = null;

        try {
            sStream = new ByteArrayInputStream(s);
            oStream = new ByteArrayOutputStream(s.length / 2);
            gzipoutputstream = new GZIPOutputStream(oStream, 1024);
            ByteStreams.copy(sStream, gzipoutputstream);

            ////////////   ------------------------------------ \\\\\\
            //gzipoutputstream.close(); // < --- Works only when placed here
            ////////////   ------------------------------------   \\\\\\

            returnValue = oStream.toByteArray();  // Here the zip is 000

        }catch(Exception e) {
            return null;
        } finally {
            if (gzipoutputstream != null) {
                gzipoutputstream.close();
            }
            if (oStream != null) {
                oStream.close();
            }
            if (sStream != null) {
                sStream.close();
            }
        }
        return returnValue;
    }
    public static void main(String[] args) throws IOException {
        String s = "12313dsfafafafaf";
        byte[] source = (byte[]) s.getBytes();
        byte[] returnZipByteArr = czip(source);
        byte[] dd =  dzip(returnZipByteArr);
        String ss = new String(dd);
        System.out.println(ss);

    }
}

这是意料之中的。 The javadoc of close() 说:

Writes remaining compressed data to the output stream and closes the underlying stream.

因此,如果您尝试在调用 close() 之前访问 ByteArrayOutputStream() 中的字节,则 gzip 压缩尚未完成:GZIP 流需要知道不会再将任何内容写入到正确写入剩余数据。

您可以调用 finish() 来获得相同的效果,但不会关闭流(因此仍然会在 finally 块中关闭它)。