Java 字符串压缩与解压的开发记录

网友投稿 349 2022-07-25


目录1、场景:2、CompressUtil类:3、注意点:4、单元测试:

1、场景:

由于数据库字段长度有限,并且不能随意的修改数据库字段的配置,数据库的某个字段设置的长度可能在设置初期是满足需求的,后期由于业务变更或业务量增大导致该字段存储的数据增长,落库时可能因为该字段数据长度过长导致落库失败,基于这种场景我们就有必要进行字符串的压缩,然后再进行落库,而落库后取出数据使用时再进行解压即可。

2、CompressUtil类:

使用java8中的gzip来进行实现

import lombok.extern.slf4j.Slf4j;

import org.apache.commons.codec.binary.Base64;

import java.io.ByteArrayInputStream;

import java.io.ByteArrayOutputStream;

import java.io.IOException;

import java.nio.charset.StandardCharsets;

import java.util.zip.GZIPInputStream;

import java.util.zip.GZIPOutputStream;

/**

* 压缩String的工具类

*/

@Slf4j

public class CompressUtil {

/**

* 使用gzip压缩字符串

* @param str 要压缩的字符串

* @return 压缩后的字符串

*/

public static String compress(String str) {

if (str == null || str.length() <= 0) {

return str;

}

ByteArrayOutputStream out = new ByteArrayOutputStream();

try (GZIPOutputStream gzip = new GZIPOutputStream(out)) {

gzip.write(str.getBytes(StandardCharsets.UTF_8));

} catch (IOException e) {

log.error("字符串压缩失败str:{},错误信息:{}", str, e.getMessage());

throw new RuntimeExhttp://ception("字符串压缩失败");

}

return Base64.encodeBase64String(out.toByteArray());

}

/**

* 使用gzip解压缩

* @param compressedStr 压缩字符串

* @return 解压后的字符串

*/

public static String uncompress(String compressedStr) {

if (compressedStr == null || compressedStr.length() <= 0) {

return compressedStr;

}

ByteArrayOutputStream out = new ByteArrayOutputStream();

ByteArrayInputStream in;

GZIPInputStream gzip = null;

byte[] compressed;

String decompressed;

try {

compressed = Base64.decodeBase64(compressedStr);

in = new ByteArrayInputStream(compressed);

gzip = new GZIPInputStream(in);

byte[] buffer = new byte[1024];

int offset;

while ((offset = gzip.read(buffer)) != -1) {

out.write(buffer, 0, offset);

}

decompressed = out.toString(StandardCharsets.UTF_8.name());

} catch (IOException e) {

log.error("字符串解压失败compressedStr:{},错误信息:{}", compressedStr, e.getMessage());

throw new RuntimeException("字符串解压失败");

} finally {

if (gzip != null) {

try {

gzip.close();

} catch (IOException ignored) {

}

}

try {

out.close();

} catch (IOException ignored) {

}

}

return decompressed;

}

}

3、注意点:

1)CompressUtil在压缩过程和解压过程使用统一字符集,防止压缩和解压过程因为字符集不同导致结果与实际预期不符;

2)在web项目中,服务器端将加密后的字符串返回给前端,前端再通过ajax请求将加密字符串发送给服务器端处理的时候,在http传输过程中会改变加密字符串的内容,导致服务器解压压缩字符串发生异常;

而CompressUtil压缩和解压过程中使用Base64.encodeBase64String和Base64.decodeBase64进行编码和解码,可以完全解决上述问题。

3)压缩/解压失败怎么处理?通过CompressUtil工具类可以看出,如果压缩或解压失败,过程发生异常,则会抛出一个运行时异常给调用方,方便调用方及时感知并处理;

具体如何处理要看具体的业务场景,我这边是在MQ消费者中调用,在MQ中统一捕获异常,所以如果压缩失败会进行重试,如果重试多次依然失败,我这边会进行报警打印日志,内部人会去处理。

4、单元测试:

import org.junit.Test;

public class CompressUtilTest {

@Test

public void test1() {

StringBuilder stringBuilder = new StringBuilder();

for(int i = 0;i < 100000;i++) {

stringBuilder.append("1");

}

System.out.println(stringBuilder.toString().length());

String compress = CompressUtil.compress(stringBuilder.toString());

System.out.println("compress="+compress);

System.out.println(compress.length());

String uncompress = CompressUtil.uncompress(compress);

System.out.println(uncompress.length());

System.out.println("uncompress=" + uncompress);

}

}

测试1:100000压缩以后为180,解压后也可以正常返回原字符串

测试2:把压缩字符串长度改为1000再试一次,压缩后长度为40

压缩比例还是很高的,亲测可用!!!


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:java中random的用法小结
下一篇:永中文档在线转换服务Swagger调用说明
相关文章

 发表评论

暂时没有评论,来抢沙发吧~