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

时间:2019-04-22 06:48:09

标签: java stream zlib gzipoutputstream

我有Zip和Unzip Text的代码。我面临着奇怪的行为-仅当我在特定位置关闭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);

    }
}

1 个答案:

答案 0 :(得分:3)

这是预期的。 The javadoc of close()说:

  

将剩余的压缩数据写入输出流并关闭基础流。

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

您可以调用finish()来达到相同的效果,但是不关闭流(因此仍然在finally块中将其关闭)。