![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5iMhRWOmVWNkBzY3gTMhNjZidzNkJzM5QTM4YWZ3M2My8CX0JXZ252bj91Ztl2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
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壓縮資料變大