如果还不是很明显,您尝试存储的字符串看起来像二进制字符串。
计数系统
二进制是一个数字base-2 https://en.wikipedia.org/wiki/Binary_number。这本质上意味着有两个字符用于计数。通常我们习惯用base-10 https://en.wikipedia.org/wiki/Decimal(十进制字符)。在计算机科学中,十六进制(base-16 https://en.wikipedia.org/wiki/Hexadecimal)也被广泛使用。
因为您不是将位存储为位而是存储为字节(use var a = 0b1100001;
如果你想像位一样存储它们)您希望存储的“二进制”只占用与任何其他具有相同长度的随机字符串一样多的空间。
由于您使用的是二进制系统,因此每个位置只有 2 个可能的值。当使用十六进制值时,单个位置最多可以容纳 16 个可能的值。对于紧凑地存储数据来说,这已经是一个很大的进步。举个例子0b11111111
and 0xff
两者都代表十进制数 255。
在您的情况下,您必须存储的每 8 个字节中就会减少 6 个字节。最后你会被困在一个只有原始字符串长度 1/4 的字符串中。
JavaScript 实现
本质上,我们想要做的是将您存储为二进制的字符串解释并检索十六进制值。幸运的是,JavaScript 内置了实现如下功能的功能:
var bin =
'1110101110100011' +
'0000101111100001' +
'1010010101011010' +
'0000110111011111' +
'1111111001010101' +
'0111000011100001' +
'1011010100110001' +
'0111111110010100' +
'0111110110100101' +
'0000111101100111' +
'1100001111011100' +
'0101011100001111' +
'0110011011001101' +
'1000110010001001' +
'1010100010000011' +
'0011110000000000';
var returnValue = '';
for (var i = 0; i < parseInt(bin.length / 8); i++) {
returnValue += parseInt(bin.substr(i*8, 8), 2).toString(16);
}
console.log(bin.length); // Will return 265
console.log(returnValue.length); // Will return 64
我们说的是“解析这个字符串并将其解释为以 2 为基数的数字,并将其存储为十六进制字符串”。
解码实际上是相同的。将上例中所有出现的数字 8 替换为 2,反之亦然。
请注意
此代码正确工作的先决条件是二进制长度能被 8 整除。请参见以下示例:
parseInt('00011110', 2).toString(16); // returns '1e'
parseInt('1e', 16).toString(2); // returns '11110'
// Technically both representations still have the same decimal value
解码时,您应该添加前导零,直到获得完整字节(8 位)。
例如,如果您必须存储的位置不能被 8 整除,您可以添加填充并在输出字符串的前面添加一个数字来标识要删除的位置。
等等,还有更多
要获得更短的字符串,您可以构建一个包含 265 个字符的查找表,在其中搜索与特定位置关联的字符。 (这是可行的,因为您仍然将十六进制值存储为字符串。)可悲的是,两者都没有ASCII https://en.wikipedia.org/wiki/ASCII也不UTF-8 https://en.wikipedia.org/wiki/UTF-8编码适合于此,因为有些块的值没有定义字符。
它可能看起来像:
// Go fill this array until you have 265 values within it.
var lookup = ['A', 'B', 'C', 'D'];
var smallerValue = lookup[0x00];
这样你就可以在一个位置有 265 个可能的值,并且你已经充分利用了你的字节。
请注意,这里没有发生真正的压缩。我们宁愿利用数据类型来更有效地用于您当前的用例。