• Java 压缩字符串 工具类


    压缩算法进行字符串压缩


    提前小结:Deflater > gzip > zip


    Deflater压缩,Inflater解压(较好)

    
    import org.apache.commons.codec.binary.Base64;
    import org.apache.commons.io.output.ByteArrayOutputStream;
    
    import java.io.UnsupportedEncodingException;
    import java.nio.charset.StandardCharsets;
    import java.util.zip.DataFormatException;
    import java.util.zip.Deflater;
    import java.util.zip.Inflater;
    
    /**
     * DeflaterUtils 压缩字符串
     */
    public class DeflaterUtils {
    
        /**
         * 压缩
         */
        public static String zipString(String unzipString) {
            /*
             *     https://www.yiibai.com/javazip/javazip_deflater.html#article-start
             *     0 ~ 9 压缩等级 低到高
             *     public static final int BEST_COMPRESSION = 9;            最佳压缩的压缩级别。
             *     public static final int BEST_SPEED = 1;                  压缩级别最快的压缩。
             *     public static final int DEFAULT_COMPRESSION = -1;        默认压缩级别。
             *     public static final int DEFAULT_STRATEGY = 0;            默认压缩策略。
             *     public static final int DEFLATED = 8;                    压缩算法的压缩方法(目前唯一支持的压缩方法)。
             *     public static final int FILTERED = 1;                    压缩策略最适用于大部分数值较小且数据分布随机分布的数据。
             *     public static final int FULL_FLUSH = 3;                  压缩刷新模式,用于清除所有待处理的输出并重置拆卸器。
             *     public static final int HUFFMAN_ONLY = 2;                仅用于霍夫曼编码的压缩策略。
             *     public static final int NO_COMPRESSION = 0;              不压缩的压缩级别。
             *     public static final int NO_FLUSH = 0;                    用于实现最佳压缩结果的压缩刷新模式。
             *     public static final int SYNC_FLUSH = 2;                  用于清除所有未决输出的压缩刷新模式; 可能会降低某些压缩算法的压缩率。
             */
    
            //使用指定的压缩级别创建一个新的压缩器。
            Deflater deflater = new Deflater(Deflater.BEST_COMPRESSION);
            //设置压缩输入数据。
            deflater.setInput(unzipString.getBytes(StandardCharsets.UTF_8));
            //当被调用时,表示压缩应该以输入缓冲区的当前内容结束。
            deflater.finish();
    
            final byte[] bytes = new byte[512];
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream(512);
    
            while (!deflater.finished()) {
                //压缩输入数据并用压缩数据填充指定的缓冲区。
                int length = deflater.deflate(bytes);
                outputStream.write(bytes, 0, length);
            }
            //关闭压缩器并丢弃任何未处理的输入。
            deflater.end();
            return Base64.encodeBase64String(outputStream.toByteArray());
            //处理回车符
    //        return zipString.replaceAll("[
    ]", "");
        }
    
        /**
         * 解压缩
         */
        public static String unzipString(String zipString) {
            byte[] decode = Base64.decodeBase64(zipString);
            //创建一个新的解压缩器  https://www.yiibai.com/javazip/javazip_inflater.html
    
            Inflater inflater = new Inflater();
            //设置解压缩的输入数据。
            inflater.setInput(decode);
            final byte[] bytes = new byte[512];
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream(512);
            try {
                //finished() 如果已到达压缩数据流的末尾,则返回true。
                while (!inflater.finished()) {
                    //将字节解压缩到指定的缓冲区中。
                    int length = inflater.inflate(bytes);
                    outputStream.write(bytes, 0, length);
                }
            } catch (DataFormatException e) {
                e.printStackTrace();
                return null;
            } finally {
                //关闭解压缩器并丢弃任何未处理的输入。
                inflater.end();
            }
    
            try {
                return outputStream.toString("UTF-8");
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
                return null;
            }
        }
    }
    
    
    

    总结

    • 压缩前的字节长度为:1825
    • 压缩后的字节长度为:284
    • 压缩率为63.73%,压缩后体积为原来的36.27%
    • 5000字符长度压缩耗时5ms(较快)

    压缩率和压缩前字节长度有一定关系,并不是随着字节长度线性增长。如:

    5000字符长度,压缩后:2500左右
    13000字符长度,压缩后:4000左右

    注:经优化,已解决偶尔出现的中文乱码问题,猜测与java的启动编码有关


    zip与Gzip压缩(还行)

    
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.util.zip.GZIPInputStream;
    import java.util.zip.GZIPOutputStream;
    import java.util.zip.ZipEntry;
    import java.util.zip.ZipInputStream;
    import java.util.zip.ZipOutputStream;
    
    /**
     * 推荐gzip
     */
    public class ZipUtils {
    
        /**
         * 使用gzip进行压缩
         */
        public static String gzip(String primStr) {
            if (primStr == null || primStr.length() == 0) {
                return primStr;
            }
    
            ByteArrayOutputStream out = new ByteArrayOutputStream();
    
            GZIPOutputStream gzip = null;
            try {
                gzip = new GZIPOutputStream(out);
                gzip.write(primStr.getBytes());
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (gzip != null) {
                    try {
                        gzip.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
    
    
            return new sun.misc.BASE64Encoder().encode(out.toByteArray());
        }
    
        /**
         * <p>Description:使用gzip进行解压缩</p>
         *
         * @param compressedStr
         * @return
         */
        public static String gunzip(String compressedStr) {
            if (compressedStr == null) {
                return null;
            }
    
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            ByteArrayInputStream in = null;
            GZIPInputStream ginzip = null;
            byte[] compressed = null;
            String decompressed = null;
            try {
                compressed = new sun.misc.BASE64Decoder().decodeBuffer(compressedStr);
                in = new ByteArrayInputStream(compressed);
                ginzip = new GZIPInputStream(in);
    
                byte[] buffer = new byte[1024];
                int offset = -1;
                while ((offset = ginzip.read(buffer)) != -1) {
                    out.write(buffer, 0, offset);
                }
                decompressed = out.toString();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (ginzip != null) {
                    try {
                        ginzip.close();
                    } catch (IOException e) {
                    }
                }
                if (in != null) {
                    try {
                        in.close();
                    } catch (IOException e) {
                    }
                }
                if (out != null) {
                    try {
                        out.close();
                    } catch (IOException e) {
                    }
                }
            }
    
            return decompressed;
        }
    
        /**
         * 使用zip进行压缩
         *
         * @param str 压缩前的文本
         * @return 返回压缩后的文本
         */
        public static final String zip(String str) {
            if (str == null)
                return null;
            byte[] compressed;
            ByteArrayOutputStream out = null;
            ZipOutputStream zout = null;
            String compressedStr = null;
            try {
                out = new ByteArrayOutputStream();
                zout = new ZipOutputStream(out);
                zout.putNextEntry(new ZipEntry("0"));
                zout.write(str.getBytes());
                zout.closeEntry();
                compressed = out.toByteArray();
                compressedStr = new sun.misc.BASE64Encoder().encodeBuffer(compressed);
            } catch (IOException e) {
                compressed = null;
            } finally {
                if (zout != null) {
                    try {
                        zout.close();
                    } catch (IOException e) {
                    }
                }
                if (out != null) {
                    try {
                        out.close();
                    } catch (IOException e) {
                    }
                }
            }
            return compressedStr;
        }
    
        /**
         * 使用zip进行解压缩
         *
         * @param compressedStr 压缩后的文本
         * @return 解压后的字符串
         */
        public static final String unzip(String compressedStr) {
            if (compressedStr == null) {
                return null;
            }
    
            ByteArrayOutputStream out = null;
            ByteArrayInputStream in = null;
            ZipInputStream zin = null;
            String decompressed = null;
            try {
                byte[] compressed = new sun.misc.BASE64Decoder().decodeBuffer(compressedStr);
                out = new ByteArrayOutputStream();
                in = new ByteArrayInputStream(compressed);
                zin = new ZipInputStream(in);
                zin.getNextEntry();
                byte[] buffer = new byte[1024];
                int offset = -1;
                while ((offset = zin.read(buffer)) != -1) {
                    out.write(buffer, 0, offset);
                }
                decompressed = out.toString();
            } catch (IOException e) {
                decompressed = null;
            } finally {
                if (zin != null) {
                    try {
                        zin.close();
                    } catch (IOException e) {
                    }
                }
                if (in != null) {
                    try {
                        in.close();
                    } catch (IOException e) {
                    }
                }
                if (out != null) {
                    try {
                        out.close();
                    } catch (IOException e) {
                    }
                }
            }
            return decompressed;
        }
        
    }
    
    

    总结

    • 压缩前的字节长度为:1825
    • 压缩后的字节长度为:307
    • 压缩率为62.04%,压缩后体积为原来的37.95%
    • 5000字符长度压缩耗时20ms(较慢)

    压缩率与字符长度关系同上


  • 相关阅读:
    python协程爬取某网站的老赖数据
    python异步回调顺序?是否加锁?
    go语言循环变量
    使用memory_profiler异常
    安装python性能检测工具line_profiler
    等我!
    pytorch代码跟着写
    Python异常类型总结
    Python项目代码阅读【不断更新】
    夏令营体会
  • 原文地址:https://www.cnblogs.com/zohnn/p/12899931.html
Copyright © 2020-2023  润新知