资讯专栏INFORMATION COLUMN

180918-JDK之Deflater压缩与Inflater解压

chemzqm / 2357人阅读

摘要:之压缩与解压解压压缩压缩与解压工具类在实际的应用场景中,特别是对外传输数据时,将原始数据压缩之后丢出去,可以说是非常常见的一个了,平常倒是没有直接使用原生的压缩工具类,使用和的机会较多正好在实际的工作场景中遇到了,现在简单的看下使用姿

title: 180918-JDK之Deflater压缩与Inflater解压
tags:

JDK

categories:

Java

JDK

date: 2018-09-18 16:53:13

keywords: JDK,Inflater,Deflater,解压,压缩 JDK 压缩与解压工具类

在实际的应用场景中,特别是对外传输数据时,将原始数据压缩之后丢出去,可以说是非常常见的一个case了,平常倒是没有直接使用JDK原生的压缩工具类,使用Protosutff和Kryo的机会较多,正好在实际的工作场景中遇到了,现在简单的看下使用姿势

I. 压缩与解压工具类 1. 基本实现

主要借助的就是Deflater, Inflater两个工具类,其使用姿势如下

</>复制代码

  1. public static String uncompress(byte[] input) throws IOException {
  2. Inflater inflater = new Inflater();
  3. inflater.setInput(input);
  4. ByteArrayOutputStream baos = new ByteArrayOutputStream(input.length);
  5. try {
  6. byte[] buff = new byte[1024];
  7. while (!inflater.finished()) {
  8. int count = inflater.inflate(buff);
  9. baos.write(buff, 0, count);
  10. }
  11. } catch (Exception e) {
  12. e.printStackTrace();
  13. } finally {
  14. baos.close();
  15. }
  16. inflater.end();
  17. byte[] output = baos.toByteArray();
  18. return new String(output, "UTF-8");
  19. }
  20. public static byte[] compress(byte[] data) throws IOException {
  21. byte[] output;
  22. Deflater compress = new Deflater();
  23. compress.reset();
  24. compress.setInput(data);
  25. compress.finish();
  26. ByteArrayOutputStream bos = new ByteArrayOutputStream(data.length);
  27. try {
  28. byte[] buf = new byte[1024];
  29. while (!compress.finished()) {
  30. int i = compress.deflate(buf);
  31. bos.write(buf, 0, i);
  32. }
  33. output = bos.toByteArray();
  34. } catch (Exception e) {
  35. output = data;
  36. e.printStackTrace();
  37. } finally {
  38. bos.close();
  39. }
  40. compress.end();
  41. return output;
  42. }

一个简单的测试

</>复制代码

  1. public static void main(String[] args) throws IOException {
  2. StringBuilder builder = new StringBuilder();
  3. for (int i = 0; i < 200; i++) {
  4. builder.append("a" + (new Random().nextInt() * 26));
  5. }
  6. String text = builder.toString();
  7. byte[] compres = compress(text.getBytes());
  8. System.out.println(compres.length + " : " + text.getBytes().length);
  9. String res = uncompress(compres);
  10. System.out.println("uncompress!
  11. " + text + "
  12. " + res);
  13. }

输出结果

</>复制代码

  1. 1011 : 1974
  2. uncompress!
  3. 1159641073884270587-148914555-876348695-140903655914152858511750740619-504526839109631208315104321891746743931-228808979-1303586499-19431155411964999751-1784318475-954798177-1812907183-831342707-3149322476028964551802022597-269963287-6384200011467670385844411707877038035412670417-1119826115558346219-959513147646693111435818855-32626587-18184494797054550038966016212145089137523302939171183465807867207-5294746515903446057333959811216956465-11772186456902770294071039871896527261-126190055310658640239029635411410052621945318513-1099749933-2044334159884087065-1705740759-1313321287-1408007761-12659778231544522691472523171153203782987609706919936632357801287155512488271333115291-1121944135941979389-179880545175884207196204559-2097788799145839653133892163716038492252042396151523357607329397509-2453452914618397691174247129-542507633-1893723573237001573-84175562119492726191070559557-875056377-1763237523-662399435-170798495-12405874171550890051-1938474621-701626601-1246867757-1138873077164155271023310391435811251050668025181338411-7641844471088518205-1570482881-1690731767-954924683-213656821149494003-544272515-9322840891981997411254437701-183054198720365002211448655569-54030518916444117051191350451-900732825-2072105047160877226512403288354302424851213478975-57604286986096457192173124564975571096304687-213425653510984804314132356831371957625714091709-327695077-182546427-372769058150182636433743131293942149315625331-1010625457741185365-81246881-565236593-1937214707-2090999425-1673181289-1110250756450022071917863643-127217577910228760391902441297-31318475-535669437-1151216791170962161121375401911260706331-1873591233-495048743-8876731551362670289-686442615-6752584831233249861-3467630691547253127-345092207-908370541-1788351797644350365-67770933-4703179231930520693138257968522450375-1171662023-5791753311816936409-1745781765-922801857281665531707439257928142703-367587763829971705455779401438501763-1398546079-606883161-924403277-1617582925-2005411841279115903
  4. 1159641073884270587-148914555-876348695-140903655914152858511750740619-504526839109631208315104321891746743931-228808979-1303586499-19431155411964999751-1784318475-954798177-1812907183-831342707-3149322476028964551802022597-269963287-6384200011467670385844411707877038035412670417-1119826115558346219-959513147646693111435818855-32626587-18184494797054550038966016212145089137523302939171183465807867207-5294746515903446057333959811216956465-11772186456902770294071039871896527261-126190055310658640239029635411410052621945318513-1099749933-2044334159884087065-1705740759-1313321287-1408007761-12659778231544522691472523171153203782987609706919936632357801287155512488271333115291-1121944135941979389-179880545175884207196204559-2097788799145839653133892163716038492252042396151523357607329397509-2453452914618397691174247129-542507633-1893723573237001573-84175562119492726191070559557-875056377-1763237523-662399435-170798495-12405874171550890051-1938474621-701626601-1246867757-1138873077164155271023310391435811251050668025181338411-7641844471088518205-1570482881-1690731767-954924683-213656821149494003-544272515-9322840891981997411254437701-183054198720365002211448655569-54030518916444117051191350451-900732825-2072105047160877226512403288354302424851213478975-57604286986096457192173124564975571096304687-213425653510984804314132356831371957625714091709-327695077-182546427-372769058150182636433743131293942149315625331-1010625457741185365-81246881-565236593-1937214707-2090999425-1673181289-1110250756450022071917863643-127217577910228760391902441297-31318475-535669437-1151216791170962161121375401911260706331-1873591233-495048743-8876731551362670289-686442615-6752584831233249861-3467630691547253127-345092207-908370541-1788351797644350365-67770933-4703179231930520693138257968522450375-1171662023-5791753311816936409-1745781765-922801857281665531707439257928142703-367587763829971705455779401438501763-1398546079-606883161-924403277-1617582925-2005411841279115903
2. 注意事项

上面这个运作的还挺好,但在接入使用时,总是提示java.util.zip.DataFormatException: incorrect header check, 因为接受的是第三方传递过来的压缩数据,比较坑爹的是对方就写了个Deflater压缩,然后什么都没有了,那么这个是啥原因呢?

其实看下Deflater的构造方法,发现还可以传一个boolean值(nowrap), 官方说明是

</>复制代码

  1. /**
  2. * Creates a new compressor using the specified compression level.
  3. * If "nowrap" is true then the ZLIB header and checksum fields will
  4. * not be used in order to support the compression format used in
  5. * both GZIP and PKZIP.
  6. * @param level the compression level (0-9)
  7. * @param nowrap if true then use GZIP compatible compression
  8. */
  9. public Deflater(int level, boolean nowrap) {
  10. this.level = level;
  11. this.strategy = DEFAULT_STRATEGY;
  12. this.zsRef = new ZStreamRef(init(level, DEFAULT_STRATEGY, nowrap));
  13. }

简单来说,就是压缩时,如果nowrap为true,那么解压时也要为true;否则对不上时,就会抛异常

接下来简单对比下两种不同传参的情况,首先更新下工具类

</>复制代码

  1. public static String uncompress(byte[] input, boolean nowrap) throws IOException {
  2. Inflater inflater = new Inflater(nowrap);
  3. inflater.setInput(input);
  4. ByteArrayOutputStream baos = new ByteArrayOutputStream(input.length);
  5. try {
  6. byte[] buff = new byte[1024];
  7. while (!inflater.finished()) {
  8. int count = inflater.inflate(buff);
  9. baos.write(buff, 0, count);
  10. }
  11. } catch (Exception e) {
  12. e.printStackTrace();
  13. } finally {
  14. baos.close();
  15. }
  16. inflater.end();
  17. byte[] output = baos.toByteArray();
  18. return new String(output);
  19. }
  20. public static byte[] compress(byte[] data, boolean nowrap) throws IOException {
  21. byte[] output;
  22. Deflater compress = new Deflater(Deflater.DEFAULT_COMPRESSION, nowrap);
  23. compress.reset();
  24. compress.setInput(data);
  25. compress.finish();
  26. ByteArrayOutputStream bos = new ByteArrayOutputStream(data.length);
  27. try {
  28. byte[] buf = new byte[1024];
  29. while (!compress.finished()) {
  30. int i = compress.deflate(buf);
  31. bos.write(buf, 0, i);
  32. }
  33. output = bos.toByteArray();
  34. } catch (Exception e) {
  35. output = data;
  36. e.printStackTrace();
  37. } finally {
  38. bos.close();
  39. }
  40. compress.end();
  41. return output;
  42. }

测试如下

</>复制代码

  1. public static void main(String[] args) throws IOException {
  2. StringBuilder builder = new StringBuilder();
  3. for (int i = 0; i < 1000; i++) {
  4. builder.append("a" + (new Random().nextInt() * 26));
  5. }
  6. String text = builder.toString();
  7. byte[] compres = compress(text.getBytes(), true);
  8. System.out.println(compres.length + " : " + text.getBytes().length);
  9. String res = uncompress(compres, true);
  10. System.out.println(res.equals(text));
  11. byte[] compres2 = compress(text.getBytes(), false);
  12. System.out.println(compres2.length + " : " + text.getBytes().length);
  13. String res2 = uncompress(compres2, false);
  14. System.out.println(res2.equals(text));
  15. }

输出结果如下,从大小来看,前者小那么一点点

</>复制代码

  1. 5086 : 9985
  2. true
  3. 5092 : 9985
  4. true
3. 小结

一般来说,jdk自带的压缩与解压,除了方便之外,可能优势并不是那么的大,这里盗一张网上的对比表格

以下来自: [[java]序列化框架性能对比(kryo、hessian、java、protostuff)](https://www.cnblogs.com/lonel...

优点 缺点
kryo 速度快,序列化后体积小 跨语言支持较复杂
hessian 默认支持跨语言 较慢
protostuff 速度快,基于protobuf 需静态编译
Protostuff-Runtime 无需静态编译,但序列化前需预先传入schema 不支持无默认构造函数的类,反序列化时需用户自己初始化序列化后的对象,其只负责将该对象进行赋值
jdk 使用方便,可序列化所有类 速度慢,占空间

其次,在使用java的压缩与解压时,需要注意下,nowrap这个参数,需要保持一致,否则会报错

II. 其他 1. 一灰灰Blog: https://liuyueyi.github.io/he...

一灰灰的个人博客,记录所有学习和工作中的博文,欢迎大家前去逛逛

2. 声明

尽信书则不如,已上内容,纯属一家之言,因个人能力有限,难免有疏漏和错误之处,如发现bug或者有更好的建议,欢迎批评指正,不吝感激

微博地址: 小灰灰Blog

QQ: 一灰灰/3302797840

3. 扫描关注

一灰灰blog

知识星球

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/77191.html

相关文章

  • Java JDK11中的新API

    摘要:将参数的所有字节写入输出流两个允许指定的新构造函数。四个允许指定的新构造函数。返回从此字符串中提取的行的流,由行终止符分隔。如上所述,使用指定的将字符编码为字节。返回此表示的执行客户端中的包装原因,如果原因不存在或未知,则返回。 有关API更改的完整列表,可在Github上获得。 这里列出的是除了java.net.http和jdk.jfr模块之外的所有新方法。没有列出java.secu...

    pepperwang 评论0 收藏0
  • Android 初级面试者拾遗(前台界面篇) ListView 和 RecyclerView

    摘要:方法根据子项所处的位置判断具体类型并返回。调用方法解除子项与之间的关联。自定义适配器适配器继承自,并将泛型指定为内部类。使用支持多种布局方式借助能够灵活地将列表控件放入不同的容器。 ListView 和 RecyclerView 最常用和最难用的控件 由于手机屏幕空间有限,无法显示全部内容。当有大量数据需要展示的时候,借助列表控件。通过手指上下滑动,使得屏幕内外的数据不断进出。 最基本...

    MartinDai 评论0 收藏0
  • Android 安全开发 ZIP 文件目录遍历

    摘要:阿里聚安全的应用漏洞扫描服务,可以检测出应用的文件目录遍历风险。阿里聚安全对开发者建议对重要的压缩包文件进行数字签名校验,校验通过才进行解压。 1、ZIP文件目录遍历简介 因为ZIP压缩包文件中允许存在../的字符串,攻击者可以利用多个../在解压时改变ZIP包中某个文件的存放位置,覆盖掉应用原有的文件。如果被覆盖掉的文件是动态链接so、dex或者odex文件,轻则产生本地拒绝服务漏洞...

    sorra 评论0 收藏0

发表评论

0条评论

chemzqm

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<