使用GZIP和压缩数据

抽象

我们都知道用zip或gzip压缩文件的含义。 但是在Java中使用压缩文件并不像您想的那样简单明了,尤其是当您不是直接使用文件而是压缩流数据时。 我们会去:

  • 如何将字符串转换为压缩/压缩字节数组,反之亦然
  • 创建用于读取和写入文件的实用程序功能,而无需事先知道文件或流是否已gzip压缩。

基础

那么,为什么要压缩任何东西? 很简单,因为这是减少必须通过网络传送或存储到磁盘的数据量的好方法,因此可以提高操作速度。 根据文档的性质,典型的文本文件或消息可以减少10倍或更多。 当然,您将不得不考虑压缩和解压缩的成本,但是当您拥有大量数据时,这些成本将不会很大。

Java支持吗?

是的,Java支持在java.util.zip包中读写gzip文件。 它还支持zip文件以及流行的ZLIB压缩库的数据膨胀和缩小。

如何压缩/解压缩Java字符串?

这是有关如何使用DeflaterOutputStream压缩和解压缩String的示例。

这是使用Java内置压缩器的两种方法以及使用GZIP的方法:

  1. 使用DeflaterOutputStream是最简单的方法:
    enum StringCompressor {
            ;
            public static byte[] compress(String text) {
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                try {
                    OutputStream out = new DeflaterOutputStream(baos);
                    out.write(text.getBytes("UTF-8"));
                    out.close();
                } catch (IOException e) {
                    throw new AssertionError(e);
                }
                return baos.toByteArray();
            }
    
            public static String decompress(byte[] bytes) {
                InputStream in = new InflaterInputStream(new ByteArrayInputStream(bytes));
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                try {
                    byte[] buffer = new byte[8192];
                    int len;
                    while((len = in.read(buffer))>0)
                        baos.write(buffer, 0, len);
                    return new String(baos.toByteArray(), "UTF-8");
                } catch (IOException e) {
                    throw new AssertionError(e);
                }
            }
        }
  2. 如果要直接使用充气机/充气机:
    enum StringCompressor2 {
            ;
            public static byte[] compress(String text) throws Exception{
                byte[] output = new byte;
                Deflater compresser = new Deflater();
                compresser.setInput(text.getBytes("UTF-8"));
                compresser.finish();
                int compressedDataLength = compresser.deflate(output);
                byte[] dest = new byte[compressedDataLength];
                System.arraycopy(output, 0, dest, 0, compressedDataLength);
                return dest;
            }
    
            public static String decompress(byte[] bytes) throws Exception{
                Inflater decompresser = new Inflater();
                decompresser.setInput(bytes, 0, bytes.length);
                byte[] result = new byte[bytes.length *10];
                int resultLength = decompresser.inflate(result);
                decompresser.end();
    
                // Decode the bytes into a String
                String outputString = new String(result, 0, resultLength, "UTF-8");
                return outputString;
            }
        }
  3. 使用GZIP的方法如下:
    enum StringGZipper {
            ;
            private static String ungzip(byte[] bytes) throws Exception{
                InputStreamReader isr = new InputStreamReader(new GZIPInputStream(new ByteArrayInputStream(bytes)), StandardCharsets.UTF_8);
                StringWriter sw = new StringWriter();
                char[] chars = new char[1024];
                for (int len; (len = isr.read(chars)) > 0; ) {
                    sw.write(chars, 0, len);
                }
                return sw.toString();
            }
    
            private static byte[] gzip(String s) throws Exception{
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                GZIPOutputStream gzip = new GZIPOutputStream(bos);
                OutputStreamWriter osw = new OutputStreamWriter(gzip, StandardCharsets.UTF_8);
                osw.write(s);
                osw.close();
                return bos.toByteArray();
            }
        }

如何解码字节流以同时允许GZip和普通流:

下面的代码将字节流转换为String(转储),而无需事先知道该流是否已压缩。

if (isGZIPStream(bytes)) {
            InputStreamReader isr = new InputStreamReader(new GZIPInputStream(new ByteArrayInputStream(bytes)), StandardCharsets.UTF_8);
            StringWriter sw = new StringWriter();
            char[] chars = new char[1024];
            for (int len; (len = isr.read(chars)) > 0; ) {
                sw.write(chars, 0, len);
            }
            dump = sw.toString();
        } else {
            dump = new String(bytes, 0, length, StandardCharsets.UTF_8);
        }
}

这是isGZIPStream方法的实现。 揭示关于GZIP_MAGIC背后的真相!

public static boolean isGZIPStream(byte[] bytes) {
        return bytes[0] == (byte) GZIPInputStream.GZIP_MAGIC 
         && bytes[1] == (byte) (GZIPInputStream.GZIP_MAGIC >>> 8);
}

这是一种在不知道文件是否已压缩的情况下读取文件的简单方法(依赖于扩展名.gz)。

static Stream<String> getStream(String dir, @NotNull String fileName) 
  throws IOException {
        File file = new File(dir, fileName);
        InputStream in;
        if (file.exists()) {
            in = new FileInputStream(file);
        } else {
            file = new File(dir, fileName + ".gz");
            in = new GZIPInputStream(new FileInputStream(file));
        }

        return new BufferedReader(new InputStreamReader(in)).lines();
}

翻译自: https://www.javacodegeeks.com/2015/01/working-with-gzip-and-compressed-data.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值