0

我有压缩和解压缩文本的代码。我面临着奇怪的行为 - 只有当我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);

    }
}
4

1 回答 1

3

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

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

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

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

于 2019-04-22T08:59:03.013 回答