java gzip 内存压缩
2016-01-22 17:43
615 查看
java 网络通讯中,为了节省带宽,可能需要将数据压缩之后再传输,正常过程如下
1. 读取原始文件 IO流
2. 用压缩工具压缩写入文件
3. 读取压缩文件IO 流
4. 传输压缩 IO 流
5. 删除压缩文件
这样一来就涉及到临时压缩文件的保存,保存完还需要删除压缩文件, 为了方便,我们直接将2、5步去除,直接将原始文件IO流压缩成压缩流,然后传输
代码如下(代码依赖于 Apache Commons Compress )
下载地址:http://commons.apache.org/proper/commons-compress/download_compress.cgi
使用方法:
1. 读取原始文件 IO流
2. 用压缩工具压缩写入文件
3. 读取压缩文件IO 流
4. 传输压缩 IO 流
5. 删除压缩文件
这样一来就涉及到临时压缩文件的保存,保存完还需要删除压缩文件, 为了方便,我们直接将2、5步去除,直接将原始文件IO流压缩成压缩流,然后传输
代码如下(代码依赖于 Apache Commons Compress )
下载地址:http://commons.apache.org/proper/commons-compress/download_compress.cgi
import java.io.IOException; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.Arrays; import java.util.zip.CRC32; import java.util.zip.Deflater; import java.util.zip.GZIPInputStream; import org.apache.commons.compress.compressors.CompressorOutputStream; import org.apache.commons.compress.compressors.gzip.GzipParameters; import org.apache.commons.compress.utils.CharsetNames; /** * gzip 压缩二进制,不写文件并返回二进制 * 修改自 org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream * @author ysq * */ public class GzipByteUtil extends CompressorOutputStream { /** Header flag indicating a file name follows the header */ private static final int FNAME = 1 << 3; /** Header flag indicating a comment follows the header */ private static final int FCOMMENT = 1 << 4; /** The underlying stream 因为该方法不需要写文件,所以不需要输出 */ //private OutputStream out; /** Deflater used to compress the data */ private final Deflater deflater; /** The buffer receiving the compressed data from the deflater */ private final byte[] deflateBuffer = new byte[512]; /** Indicates if the stream has been closed */ private boolean closed; /** The checksum of the uncompressed data */ private final CRC32 crc = new CRC32(); private byte[] compressedByte; /** * Creates a gzip compressed output stream with the default parameters. */ public GzipByteUtil() throws IOException { this(new GzipParameters()); } /** * 不需要写文件所以不需要 out 对象 * * @since 1.7 */ public GzipByteUtil(GzipParameters parameters) throws IOException { //this.out = out; this.deflater = new Deflater(parameters.getCompressionLevel(), true); writeHeader(parameters); } /** * 返回压缩后的完整二进制 * @return */ public byte[] getCompressedByte() { return compressedByte; } /** * 头文件写文件,改为返回头文件二进制 * @param parameters * @throws IOException */ private void writeHeader(GzipParameters parameters) throws IOException { String filename = parameters.getFilename(); String comment = parameters.getComment(); ByteBuffer buffer = ByteBuffer.allocate(10); buffer.order(ByteOrder.LITTLE_ENDIAN); buffer.putShort((short) GZIPInputStream.GZIP_MAGIC); buffer.put((byte) Deflater.DEFLATED); // compression method (8: deflate) buffer.put((byte) ((filename != null ? FNAME : 0) | (comment != null ? FCOMMENT : 0))); // flags buffer.putInt((int) (parameters.getModificationTime() / 1000)); // extra flags int compressionLevel = parameters.getCompressionLevel(); if (compressionLevel == Deflater.BEST_COMPRESSION) { buffer.put((byte) 2); } else if (compressionLevel == Deflater.BEST_SPEED) { buffer.put((byte) 4); } else { buffer.put((byte) 0); } buffer.put((byte) parameters.getOperatingSystem()); compressedByte = buffer.array(); //out.write(compressedByte); if (filename != null) { byte[] nameByte = filename.getBytes(CharsetNames.ISO_8859_1); ByteBuffer nbf = ByteBuffer.allocate(nameByte.length + 1); nbf.put(nameByte); nbf.put((byte) 0); appendCompressedByte(nbf.array()); //out.write(filename.getBytes(CharsetNames.ISO_8859_1)); //out.write(nbf.array()); } if (comment != null) { byte[] commentByte = comment.getBytes(CharsetNames.ISO_8859_1); ByteBuffer combf = ByteBuffer.allocate(commentByte.length + 1); combf.put(commentByte); combf.put((byte) 0); appendCompressedByte(combf.array()); //out.write(combf.array()); } } /** ===================================================================================================== **/ @Override public void write(int b) throws IOException { write(new byte[]{(byte) (b & 0xff)}, 0, 1); } /** * {@inheritDoc} * * @since 1.1 */ @Override public void write(byte[] buffer) throws IOException { write(buffer, 0, buffer.length); } /** * {@inheritDoc} * * @since 1.1 */ @Override public void write(byte[] buffer, int offset, int length) throws IOException { if (deflater.finished()) { throw new IOException("Cannot write more data, the end of the compressed data stream has been reached"); } else if (length > 0) { deflater.setInput(buffer, offset, length); while (!deflater.needsInput()) { deflate(); } crc.update(buffer, offset, length); } } private void deflate() throws IOException { int length = deflater.deflate(deflateBuffer, 0, deflateBuffer.length); if (length > 0) { byte[] defByte = Arrays.copyOfRange(deflateBuffer, 0, length); appendCompressedByte(defByte); //out.write(defByte); } } private void writeTrailer() throws IOException { ByteBuffer buffer = ByteBuffer.allocate(8); buffer.order(ByteOrder.LITTLE_ENDIAN); buffer.putInt((int) crc.getValue()); buffer.putInt(deflater.getTotalIn()); byte[] traByte = buffer.array(); appendCompressedByte(traByte); //out.write(traByte); } /** * Finishes writing compressed data to the underlying stream without closing it. * * @since 1.7 */ public void finish() throws IOException { if (!deflater.finished()) { deflater.finish(); while (!deflater.finished()) { deflate(); } writeTrailer(); } } @Override public void close() throws IOException { if (!closed) { finish(); deflater.end(); //out.close(); closed = true; } } /** * 追加压缩后的数组 * @param append */ public void appendCompressedByte(byte[] append){ int originalLength = compressedByte.length; int appendLength = append.length; //先扩容长度 int totalLength = originalLength + appendLength; compressedByte = Arrays.copyOf(compressedByte, totalLength); System.arraycopy(append, 0, compressedByte, originalLength, appendLength); } }
使用方法:
/** * 文件压缩 */ public static void copyTest(){ String pathFrom = "D:/testFile/compress/compress.txt"; String pathTo = "D:/testFile/compress/compress.txt.gz"; try { GzipParameters parameters = new GzipParameters(); parameters.setFilename("test"); parameters.setCompressionLevel(5); InputStream input = new FileInputStream(pathFrom); OutputStream output = new FileOutputStream(pathTo); GzipByteUtil gzipOut = new GzipByteUtil(parameters); byte[] readByte = new byte[1024 * 4]; int length; while((length = input.read(readByte)) != -1){ gzipOut.write(readByte, 0, length); gzipOut.flush(); } gzipOut.close(); //获取压缩二进制 byte[] resultByte = gzipOut.getCompressedByte(); output.write(resultByte); System.out.println(resultByte.length); output.close(); input.close(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序
- 二叉查找树