有限字符集的字符串压缩算法

news/2024/12/2 7:08:09/

概述

在开发中,经常有上报线上堆栈来分析处理线上问题的场景,所以,对堆栈的压缩和加密也是必不可少的。加密:可以使用AES对称加密算法,压缩:可以在上传时利用protobuf天生的压缩性对字符串进行压缩。

不过,出于对流量的节省和传输效率的提升,可以通过在堆栈上传前先压缩一次数据来保证。下面给大家介绍一种笔者自己摸索的一种压缩字符串的算法,并且自带加密效果。

算法介绍

此算法使用场景:有限字符集的字符串压缩。

例如Java方法全限定名的压缩,对于方法全限定来说,组成成分:大小写英文字母,数字,特殊字符。在开发过程中,一个标准且合格的类名,方法名需要做到见名知意,根据有效统计,方法全限定99%以上由大小写英文字母组成。

算法实现

压缩原理简述
将char字符的空闲bit位来存储有效的数据。比如通过将 a ~ z 映射成 1 ~ 26 的数字,并将Char类型以5bit为一组分为高、中、低三组,分别来存储一个数字(这一个数字代表一个字符)

建立字符串头结构: Head

在Java代码编写过程中,一个全限定字符串中的大写字母占比相对较小,因此,通过使用前补充字符的方式来记录全限定字符串中的大写字母。一个字符串如果是有限且不可变的,那么所组成他们的字符之间的相对位置是确定的。实现算法如下:

public char[] build(String s) {...for (int i = 0; i < len; i++) {c = s.charAt(i);b = Character.isUpperCase(c);if (b || c == FILL) {if (i - lastIndex >= maxDistance) {maxDistance = i - lastIndex;}upCharIndex.add(i - lastIndex);lastIndex = i;}if (b) upCharCount++;}...return handleHead(type);
} 

在压缩前的第一步:在字符串开始时,保存并记录大写字母的位置和每一个大写字母之间的距离。(小数点认为是一个大写字母)。

 private char[] handleHead(int type) {...int k, j;//记录大写字母位置与char中for (int i = 0; i < chars.length; i++) {if (i == 0) {for (j = 0, k = 1; j < ch1; j++, k++) {ch = bitToLeft(ch, upCharIndex.get(j), 12 - (k * stepDistance));}chars[i] = ch;} else {char emptyCh = FILL;emptyCh &= 0;int start = (i - 1) * sizeOfChar + ch1;for (j = start, k = 1; j < start + sizeOfChar; j++, k++) {if (j == upCharIndex.size())break;emptyCh = bitToLeft(emptyCh, upCharIndex.get(j), 16 - (k * stepDistance));}chars[i] = emptyCh;}}return chars;
} 

Head的最小长度为:1个Char,也就是16bit。在16bit的高2位存储步长。接下来的2位记录真正的Head长度大小。

head长度:Head最小的长度是1个Char,其中记录步长和Head长度的信息。目前,填充长度最长为 3+1,可通过步长算法完成Head长度的扩展。扩展方法:getTypeBySize、getSizeByType

存储大写字母的位置时,按照步长来填充。例如:步长为3,那么就意味着每3个bit存储一个大写字母位置。
Head的长度取决于填充了多少个步长。例如:填充10个步长为3的位置,需要16%3等于5,那么就需要两个Char.

步长: 步长是一个可变的量,在算法设计中,提供如下几种步长类型:(据统计最长英文单词:45个字符)STEP_0:表示没有大写字母STEP_3:表示大写字母距离(0,8),步长为3STEP_15:表示大写字母间距离[816),步长为4STEP_OVER_15:表示大写字母间距离[1663),步长为6

建立压缩字符串内容:Content

Content压缩是按照1个Char的高、中、低三位中分别存储一个字符的算法完成的。具体的实现FormatUtil.ContentBuilder:

填充: 由于字符串并不都是3的倍数。为了保证原字符串的完整性,在分割字符串之前先给原来字符串填充一定数量的字符,保证其在分割的时候可以每3个字符为一组。

 public String handleString(String s) {int f;if ((f = s.length() % 3) != 0) {StringBuilder sBuilder = new StringBuilder(s);for (f = 3 - f; f > 0; f--)sBuilder.append(FILL);s = sBuilder.toString();}return s.toLowerCase();
} 

分割替换: 在完成填充以后,将原来的字符串以三个为一组分割成多个组。对于字符串中的数字或者特殊字符,我们在mapping文件中并没有形成映射,因此,一旦出现,那么就通过“MASK”去代替。

public short buildShort(char high, char mid, char low) {short b = 0;b |= getShortFromMapping(high) << 10;b |= getShortFromMapping(mid) << 5;b |= getShortFromMapping(low);return b;
}public short getShortFromMapping(char ch) {if (mapping.containsKey(ch))return mapping.get(ch);return mapping.get(MASK);
} 

建立完成压缩后字符串

Head + content = 压缩完成后的字符串。

总结

在算法构思前期,理论压缩效率可达66%:将三个Char存储在一个Char中,不过从最后包大小的总压缩率来计算,压缩率应该只有50%左右。出现这种的情况的原因如下:

    字符串长度不都是3的整数倍,有多余的字符填充压缩完以后的字符并不是一个正确的ASCII码,在Java底层对字符集的编解码过程中,将其认为是汉字,一次一个字符会被解码成两个字符大小。

http://www.ppmy.cn/news/633855.html

相关文章

ansible实训-Day2(ansible基本问题及部署安装)

一、前言 该篇是对ansible实训第二天内容的归纳总结&#xff0c;主要包括ansible的一些基本问题以及ansible的部署安装。 二、理论部分 Q1&#xff1a;什么是ansible Ansible是一种自动化IT工具&#xff0c;它可以帮助管理和自动化IT基础架构。使用Ansible&#xff0c;管理员…

iPhone苹果手机尺寸大小

iphone 5 &#xff1a;300px iPhone 6&#xff1a;348px iPhone 6S plus&#xff1a; 348 px

微服务springcloud 10.config配置中心框架和rabbitmq的安装

config配置中心的作用&#xff1a;项目的yml 配置文件保存到 git 服务器&#xff0c;例如 github.com 或 gitee.com 微服务启动时&#xff0c;从服务器获取配置文件 1.新建 “Project”,命名为 config。注意这里的不是maven项目&#xff0c;而是project 2.将sp02,sp03,sp04,s…

6s测试信号软件,主流智能机信号强度测试 iPhone6s表现差

据外媒报道&#xff0c;最近丹麦Aalborg大学的教授Gert Frolund Pedersen对苹果iPhone 6s的天线性能进行了试验&#xff0c;不过从结果来看并不是十分乐观。 Pedersen将iPhone 6s与之前的iPhone 6、三星Galaxy S6和索尼Xperia Z5 Compact进行对比&#xff0c;测试其在900GSM频段…

ios 改变图片尺寸_iOS 修改图片尺寸的方法

目前在iOS上对于图片的优化点有很多,例如图片解码、图片渐加载和图片尺寸处理。这篇文章是说明目前iOS 代码中修改图片尺寸的两种方法,以及这两种方法区别和注意点。 修改图片尺寸的两种方法 1. 画布ImageContext(UIKit) /** 利用画布对图片尺寸进行修改 @param data ---- 图…

6s测试信号软件,手机信号强度测试:苹果iPhone 6s不敌三星S6

10月29日消息&#xff0c;来自丹麦Aalborg大学教授Gert Frolund Pedersen曾发现苹果iPhone 4“天线门”问题而在科技圈名声大噪。近日&#xff0c;他又对苹果iPhone 6s的天线性能进行了试验&#xff0c;不过从结果来看并不是十分乐观。 教授在封闭的环境中对37款智能手机进行测…

vscode cpp使用gtest进行测试

在 VS Code 中使用 Google Test (gtest) 进行 C 代码测试需要进行一些设置和配置&#xff1a; 安装 Google Test&#xff1a;首先&#xff0c;你需要下载并安装 Google Test 框架。你可以从官方 GitHub 仓库&#xff08;https://github.com/google/googletest&#xff09;下载源…

最小化安装的Red Hat 9安装完Zabbix后没有中文字体报错解决

Redhat9最小化安装后&#xff0c;将 Zabbix 的界面设置为中文&#xff0c;但是系统提示你服务器上没有安装相应的语言包。这是因为 Zabbix 需要在服务器上安装相应的语言环境才能正常显示相应的语言。 报错提示&#xff1a; You are not able to choose some of the languages,…