
gzip压缩数据变大
抽象
我们都知道用zip或gzip压缩文件的含义。 但是在Java中使用压缩文件并不像您想的那样简单明了,尤其是如果您不是直接处理文件而是压缩流数据的话。 我们会去:
- 如何将字符串转换为压缩/压缩字节数组,反之亦然
- 创建用于读取和写入文件的实用程序功能,而无需事先知道文件或流是否已gzip压缩。
基础
那么,为什么要压缩任何东西? 很简单,因为这是减少必须通过网络传送或存储到磁盘的数据量的好方法,因此可以提高操作速度。 根据文档的性质,典型的文本文件或消息可以减少10倍或更多。 当然,您将不得不考虑压缩和解压缩的成本,但是当您拥有大量数据时,这些成本将不会很大。
Java支持吗?
是的,Java支持在java.util.zip包中读写gzip文件。 它还支持zip文件以及流行的ZLIB压缩库的数据膨胀和缩小。
如何压缩/解压缩Java字符串?
这是一个如何使用DeflaterOutputStream压缩和解压缩String的示例。
这是使用Java内置压缩器的两种方法以及使用GZIP的方法:
- 使用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); } } }
- 如果要直接使用充气机/充气机:
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; } }
- 使用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
gzip压缩数据变大