前言

之前用JavaScript实现过gzip压缩字符串的功能
链接: Javascript 实现Gzip 压缩字符串

这次是再用Java实现一次Gzip对于字符串的压缩和解压缩

另外简单说明一下Gzip
1. Gzip是一种压缩程序的格式,和zip rar 7z差不多,本文利用的是Gzip把字符串压缩成二进制byte[]
2. 压缩后的内容会再用base64编码变回base64字符串方便传输和存储数据库
3. 压缩后的内容不一定比压缩前的要短,取决于重复的字符多不多,原文长度够不够长
4. 下文代码只用原生Java 8的内部依赖,只有一个外部依赖是StringUtils 也可以用Java8的语言来写,我只是懒得再写一遍



代码

  1. import org.apache.commons.lang.StringUtils;
  2. import java.io.ByteArrayInputStream;
  3. import java.io.ByteArrayOutputStream;
  4. import java.util.Base64;
  5. import java.util.zip.GZIPInputStream;
  6. import java.util.zip.GZIPOutputStream;
  7. /**
  8. * @author zmh
  9. * @date 2020-01-07
  10. * <p>
  11. * Gzip压缩字符串工具类
  12. */
  13. public class GzipUtils {
  14. public static final String GZIP_ENCODE_UTF_8 = "UTF-8";
  15. /**
  16. * base64 编码
  17. *
  18. * @param bytes 传入bytes
  19. * @return 编码成string类型的base64返回
  20. */
  21. public static String base64encode(byte[] bytes) {
  22. return new String(Base64.getEncoder().encode(bytes));
  23. }
  24. /**
  25. * base64 解码
  26. *
  27. * @param string 传入string类型的base64编码
  28. * @return 解码成byte类型返回
  29. */
  30. public static byte[] base64decode(String string) {
  31. return Base64.getDecoder().decode(string);
  32. }
  33. /**
  34. * 压缩字符串
  35. *
  36. * @param string 需要压缩的字符串
  37. * @return 压缩后内容 并转base64 返回
  38. */
  39. public static String gzip(String string) {
  40. String result = "";
  41. if (StringUtils.isBlank(string)) {
  42. return result;
  43. }
  44. ByteArrayOutputStream out = new ByteArrayOutputStream();
  45. GZIPOutputStream gzip;
  46. try {
  47. gzip = new GZIPOutputStream(out);
  48. gzip.write(string.getBytes(GZIP_ENCODE_UTF_8));
  49. gzip.close();
  50. out.close();
  51. result = base64encode(out.toByteArray());
  52. } catch (Exception e) {
  53. e.printStackTrace();
  54. }
  55. return result;
  56. }
  57. /**
  58. * 解压缩字符串
  59. *
  60. * @param string base64格式的压缩后字符串
  61. * @return 解码并解压缩后返回
  62. */
  63. public static String unGzip(String string) {
  64. String result = "";
  65. if (StringUtils.isBlank(string)) {
  66. return result;
  67. }
  68. ByteArrayOutputStream out = new ByteArrayOutputStream();
  69. ByteArrayInputStream in;
  70. GZIPInputStream ungzip;
  71. byte[] bytes = base64decode(string);
  72. try {
  73. in = new ByteArrayInputStream(bytes);
  74. ungzip = new GZIPInputStream(in);
  75. byte[] buffer = new byte[1024];
  76. int len = 0;
  77. while ((len = ungzip.read(buffer)) != -1) {
  78. out.write(buffer, 0, len);
  79. }
  80. ungzip.close();
  81. out.close();
  82. in.close();
  83. result = out.toString(GZIP_ENCODE_UTF_8);
  84. } catch (Exception e) {
  85. e.printStackTrace();
  86. }
  87. return result;
  88. }
  89. public static void main(String[] args) {
  90. long temp = System.currentTimeMillis();
  91. String test = "Gzip压压压压缩缩缩缩缩测试测试测试测试测试试试试试试试试试试试aaaabbbbbccccccaaaabbbbbccccccaaaabbbbbccccccdddddd111111111111111111111111111111111111111";
  92. String gzip = gzip(test);
  93. String unGzip = unGzip(gzip);
  94. System.out.println("原文:" + test);
  95. System.out.println("Gzip压缩:" + gzip);
  96. System.out.println("Gzip解压:" + unGzip);
  97. System.out.println("整体消耗时间: " + (System.currentTimeMillis() - temp) + " ms");
  98. }
  99. }

执行结果

  1. 原文:Gzip压压压压缩缩缩缩缩测试测试测试测试测试试试试试试试试试试试aaaabbbbbccccccaaaabbbbbccccccaaaabbbbbccccccdddddd111111111111111111111111111111111111111
  2. Gzip压缩:H4sIAAAAAAAAAHOvyix42tcNR8/3rERGz7Z2v1g/FReJHyUCQRIIJIMBfm4KGBgSBwDGzrxFtQAAAA==
  3. Gzip解压:Gzip压压压压缩缩缩缩缩测试测试测试测试测试试试试试试试试试试试aaaabbbbbccccccaaaabbbbbccccccaaaabbbbbccccccdddddd111111111111111111111111111111111111111
  4. 整体消耗时间: 39 ms


END

补充:经测试,发现Gzip的压缩率其实挺高,但仅限于压缩成Byte[],如果再把Byte[]转成base64,会增加大小,所以这里可以根据需求,来考虑是否可以直接用二进制存储和传输