JS压缩字符串
最近项目中使用到了压缩字符串的功能,在网上查阅了很多,也有很多处理方式。有引入js库的,也有原生的方式完成的。压缩完成后的字符串乱码,如果不想要乱码的字符串可以不用查看了。
引入js库实现
使用lz-string.js文件
引入
<script type="text/javascript" src="./lz-string.min.js"></script>
使用
var string = "Lorem Ipsum is simply dummy text of the printing and typesetting industry.";
console.log("Size of sample is: " + string.length);
var compressed = LZString.compress(string);
console.log("Size of compressed sample is: " + compressed.length);
console.log(compressed);
string = LZString.decompress(compressed);
console.log("Sample is: " + string);
打印效果
主要实现方式:压缩(LZString.compress),解压缩(LZString.decompress)
js原生实现
直接上代码
/**
* 压缩字符串
*/
function compress(strNormalString) {
var strCompressedString = "";
var ht = new Array();
for (i = 0; i < 128; i++) {
ht[i] = i;
}
var used = 128;
var intLeftOver = 0;
var intOutputCode = 0;
var pcode = 0;
var ccode = 0;
var k = 0;
for (var i = 0; i < strNormalString.length; i++) {
ccode = strNormalString.charCodeAt(i);
k = (pcode << 8) | ccode;
if (ht[k] != null) {
pcode = ht[k];
} else {
intLeftOver += 12;
intOutputCode <<= 12;
intOutputCode |= pcode;
pcode = ccode;
if (intLeftOver >= 16) {
strCompressedString += String.fromCharCode(intOutputCode >> (intLeftOver - 16));
intOutputCode &= (Math.pow(2, (intLeftOver - 16)) - 1);
intLeftOver -= 16;
}
if (used < 4096) {
used++;
ht[k] = used - 1;
}
}
}
if (pcode != 0) {
intLeftOver += 12;
intOutputCode <<= 12;
intOutputCode |= pcode;
}
if (intLeftOver >= 16) {
strCompressedString += String.fromCharCode(intOutputCode >> (intLeftOver - 16));
intOutputCode &= (Math.pow(2, (intLeftOver - 16)) - 1);
intLeftOver -= 16;
}
if (intLeftOver > 0) {
intOutputCode <<= (16 - intLeftOver);
strCompressedString += String.fromCharCode(intOutputCode);
}
return strCompressedString;
}
/* *
* 解压缩字符串
*/
function decompress(strCompressedString) {
var strNormalString = "";
var ht = new Array();
for (i = 0; i < 128; i++) {
ht[i] = String.fromCharCode(i);
}
var used = 128;
var intLeftOver = 0;
var intOutputCode = 0;
var ccode = 0;
var pcode = 0;
var key = 0;
for (var i = 0; i < strCompressedString.length; i++) {
intLeftOver += 16;
intOutputCode <<= 16;
intOutputCode |= strCompressedString.charCodeAt(i);
while (1) {
if (intLeftOver >= 12) {
ccode = intOutputCode >> (intLeftOver - 12);
if (typeof (key = ht[ccode]) != "undefined") {
strNormalString += key;
if (used > 128) {
ht[ht.length] = ht[pcode] + key.substr(0, 1);
}
pcode = ccode;
} else {
key = ht[pcode] + ht[pcode].substr(0, 1);
strNormalString += key;
ht[ht.length] = ht[pcode] + key.substr(0, 1);
pcode = ht.length - 1;
}
used++;
intLeftOver -= 12;
intOutputCode &= (Math.pow(2, intLeftOver) - 1);
} else {
break;
}
}
}
return strNormalString;
}
效果图片如下
实现压缩中文字符串
以上两种方式不能实现压缩中文字符串,所以我最开始想的是将中文字符串转换成拼音,然后压缩,在想想拼音解压回来可能不正确。所以我最后选择的方式是将中文转换成16进制,将16进制压缩,然后解压转换
转换16进制方法如下
function chToHex(ch) { //汉字字符转16进制
if (ch) {
var arr = ch.split('')
var res = ''
for (var i = 0; i < arr.length; i++) {
res += arr[i].charCodeAt().toString(16)
if (i != arr.length - 1) { res += ',' }
}
console.log(res) // 5468,516d
return res
}
return false
}
function hexToCh(ch) { //16进制转汉字
if (ch) {
var arr = ch.split(',')
var res = ''
for (var i = 0; i < arr.length; i++) {
res += String.fromCharCode(parseInt(arr[i], 16))
}
console.log(res) // 周六
return res
}
return false
}
具体实现的一个小demo
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>压缩字符串方法</title>
<style type="text/css">
</style>
</head>
<div style="text-align: center; color: cornflowerblue; height: 100%;">
<span id="spanText">cesfafsfadsfas</span></br>
<button onclick="changeText()">点击修改数据</button></br>
<button onclick="reductionText()">点击还原数据</button></br>
</div>
<script type="text/javascript" src="./lz-string.min.js"></script>
<script type="text/javascript">
// 外部jar包引用
var string = "Lorem Ipsum is simply dummy text of the printing and typesetting industry.";
console.log("Size of sample is: " + string.length);
var compressed = LZString.compress(string);
console.log("Size of compressed sample is: " + compressed.length);
console.log(compressed);
string = LZString.decompress(compressed);
console.log("Sample is: " + string);
let isChange = 0
function changeText() {
if (isChange === 0) {
let text = document.getElementById('spanText').innerText
let newText = chToHex(text)
let changeText = compress(newText)
document.getElementById('spanText').innerText = changeText
isChange = 1
} else {
alert('当前展示文本已经压缩,请解压后操作')
return false
}
}
function reductionText() {
if (isChange === 1) {
let text = document.getElementById('spanText').innerText
console.log('原始数据', text)
let reductionText = decompress(text)
console.log('解压完成数据', reductionText)
let reg = new RegExp("[\\u4E00-\\u9FFF]+", "g")
if (reg.test(reductionText)) {
console.log('包含中文')
}
let newText = hexToCh(reductionText)
document.getElementById('spanText').innerText = newText
isChange = 0
} else {
alert('当前展示文本还未压缩,请压缩后操作')
return false
}
}
/**
* 压缩字符串
*/
function compress(strNormalString) {
var strCompressedString = "";
var ht = new Array();
for (i = 0; i < 128; i++) {
ht[i] = i;
}
var used = 128;
var intLeftOver = 0;
var intOutputCode = 0;
var pcode = 0;
var ccode = 0;
var k = 0;
for (var i = 0; i < strNormalString.length; i++) {
ccode = strNormalString.charCodeAt(i);
k = (pcode << 8) | ccode;
if (ht[k] != null) {
pcode = ht[k];
} else {
intLeftOver += 12;
intOutputCode <<= 12;
intOutputCode |= pcode;
pcode = ccode;
if (intLeftOver >= 16) {
strCompressedString += String.fromCharCode(intOutputCode >> (intLeftOver - 16));
intOutputCode &= (Math.pow(2, (intLeftOver - 16)) - 1);
intLeftOver -= 16;
}
if (used < 4096) {
used++;
ht[k] = used - 1;
}
}
}
if (pcode != 0) {
intLeftOver += 12;
intOutputCode <<= 12;
intOutputCode |= pcode;
}
if (intLeftOver >= 16) {
strCompressedString += String.fromCharCode(intOutputCode >> (intLeftOver - 16));
intOutputCode &= (Math.pow(2, (intLeftOver - 16)) - 1);
intLeftOver -= 16;
}
if (intLeftOver > 0) {
intOutputCode <<= (16 - intLeftOver);
strCompressedString += String.fromCharCode(intOutputCode);
}
return strCompressedString;
}
/* *
* 解压缩字符串
*/
function decompress(strCompressedString) {
var strNormalString = "";
var ht = new Array();
for (i = 0; i < 128; i++) {
ht[i] = String.fromCharCode(i);
}
var used = 128;
var intLeftOver = 0;
var intOutputCode = 0;
var ccode = 0;
var pcode = 0;
var key = 0;
for (var i = 0; i < strCompressedString.length; i++) {
intLeftOver += 16;
intOutputCode <<= 16;
intOutputCode |= strCompressedString.charCodeAt(i);
while (1) {
if (intLeftOver >= 12) {
ccode = intOutputCode >> (intLeftOver - 12);
if (typeof (key = ht[ccode]) != "undefined") {
strNormalString += key;
if (used > 128) {
ht[ht.length] = ht[pcode] + key.substr(0, 1);
}
pcode = ccode;
} else {
key = ht[pcode] + ht[pcode].substr(0, 1);
strNormalString += key;
ht[ht.length] = ht[pcode] + key.substr(0, 1);
pcode = ht.length - 1;
}
used++;
intLeftOver -= 12;
intOutputCode &= (Math.pow(2, intLeftOver) - 1);
} else {
break;
}
}
}
return strNormalString;
}
chToHex()
hexToCh()
function chToHex(ch) { //汉字字符转16进制
if (ch) {
var arr = ch.split('')
var res = ''
for (var i = 0; i < arr.length; i++) {
res += arr[i].charCodeAt().toString(16)
if (i != arr.length - 1) { res += ',' }
}
console.log(res) // 5468,516d
return res
}
return false
}
function hexToCh(ch) { //16进制转汉字
if (ch) {
var arr = ch.split(',')
var res = ''
for (var i = 0; i < arr.length; i++) {
res += String.fromCharCode(parseInt(arr[i], 16))
}
console.log(res) // 周六
return res
}
return false
}
</script>
</body>
</html>
展示效果
参考博客:
十六进制转换:https://blog.csdn.net/weixin_43939111/article/details/114830133
字符串压缩:https://blog.csdn.net/qq285679784/article/details/126996720