Snappy是Google開源的壓縮/解壓縮庫。和其餘壓縮庫相比,snappy的壓縮率並非最高的,兼容性也並不是最好的。相反,它的誕生旨在以極高的壓縮/解壓縮速率提供合理的壓縮率。Snappy官指出:在64位單核core-i7處理器下,snappy的壓縮率可以達到250MB/S,而解壓縮速度則能達到500MB/S。目前不少軟件使用(或支持)snappy做爲壓縮庫,如MongoDB,Cassandra,Hadoop,Lucene…本文簡單介紹snappy Java Api的使用。java
Snappy提供了不少高級API以方便對byte[],Sting,double[]等進行壓縮和解壓縮,示例代碼以下:
app
import org.xerial.snappy.Snappy; String input = "Hello snappy-java! Snappy-java is a JNI-based wrapper of Snappy, a fast compresser/decompresser."; { byte[] compressed = Snappy.compress(input.getBytes("UTF-8")); byte[] uncompressed = Snappy.uncompress(compressed); String result = new String(uncompressed, "UTF-8"); System.out.println(result); } { byte[] compressed = Snappy.compress(input); System.out.println(Snappy.uncompressString(compressed)); } { double [] arr = new double[]{123.456,234.567,345.678}; byte[] compressed = Snappy.compress(arr); double [] unarr = Snappy.uncompressDoubleArray(compressed); System.out.println(Arrays.toString(unarr)); }
同時Snappy仍然保留着低級API,用於最小化內存的拷貝,例如oop
/* *inputAddr:待壓縮數據的內存地址 *inputSize:待壓縮數據的byte size *destAddr:壓縮結果的保存地址 *return:返回壓縮後數據的大小 */ public static long rawCompress(long inputAddr,long inputSize, long destAddr)throws java.io.IOException; /* *inputAddr:待解壓縮數據的內存地址 *inputSize:待解壓縮數據的byte size *destAddr:解壓縮結果的保存地址 *return:返回解壓縮後數據的大小 */ public static long rawUncompress(long inputAddr,long inputSize,long destAddr)throws java.io.IOException;
基於輸入/輸出流的Snappy解壓縮
SnappyOutputStream和SnappyInputStream分別用於流數據的壓縮/解壓縮。此外,從snappy v1.1.0開始提供了Framing-format(幀格式)輸入輸出流的壓縮/解壓縮的方法:SnappyFramedOutputStream和SnappyFramedInputStream。須要注意的是以SnappyOutputStream壓縮的數據不能以SnappyFramedInputStream方法解開,反之亦然。下面以SnappyOutputStream和SnappyInputStream爲例介紹。
SnappyOutputStream繼承自java.io OutputStream,重寫了經常使用的的write,close,flush:
code
File file = new File("..."); //待壓縮文件 File out = new File("./", file.getName() + ".snappy"); //壓縮結果文件 byte[] buffer = new byte[1024 * 1024 * 8]; FileInputStream fi = null; FileOutputStream fo = null; SnappyOutputStream sout = null; try { fi = new FileInputStream(file); fo = new FileOutputStream(out); sout = new SnappyOutputStream(fo); while(true) { int count = fi.read(buffer, 0, buffer.length); if(count == -1) { break; } sout.write(buffer, 0, count); } sout.flush(); } catch(Throwable ex) { ex.printStackTrace(); } finally { if(sout != null) {try { sout.close();} catch (Exception e) {}} if(fi != null) { try { fi.close(); } catch(Exception x) {} } if(fo != null) { try { fo.close(); } catch(Exception x) {} } }
SnappyInputStream 繼承自java.io InputStream,重寫了經常使用的read,close方法等orm
File file = new File("xxx"); //待解壓文件 File out = new File("xxx"); //解壓後文件 byte[] buffer = new byte[1024 * 1024 * 8]; FileInputStream fi = null; FileOutputStream fo = null; SnappyInputStream sin = null; try { fo = new FileOutputStream(out); fi = new FileInputStream(file.getPath()); sin = new SnappyInputStream(fi); while(true) { int count = sin.read(buffer, 0, buffer.length); if(count == -1) { break; } fo.write(buffer, 0, count); } fo.flush(); } catch(Throwable ex) { ex.printStackTrace(); } finally { if(sin != null) { try { sin.close(); } catch(Exception x) {} } if(fi != null) { try { fi.close(); } catch(Exception x) {} } if(fo != null) { try { fo.close(); } catch(Exception x) {} } }