将二进制字符串编码为任意字母

时间:2019-02-12 02:32:47

标签: string encoding binary bit-manipulation

如果您将一组二进制字符串限制为通常较小的大小(例如256或最多512字节)(例如某些哈希算法),那么如果要对这些 bits 进行编码将1和0的整数表示为十六进制(一个16个字符的字母),然后您将整个字符串立即带入内存,然后将其转换为十六进制。至少那是我认为的意思。

我没有完全解决这个问题,但是我想知道的是,您是否可以将任意长的二进制字符串转换为某些字母,而则无需读取整个字符串进入内存。这不是一个完整的问题,是因为我不确定您是否通常 do 将整个字符串读入内存以创建编码版本。

所以,如果您有这样的事情:

  

... 1011101010011011011101010011011011101010011011110011011110110110111101001100101010010100100000010111101110101001101101110101001101101110101001101111001101111011011011110100110010101001010010000001011110111010100110110111010100110110111010100110111100111011101010011011011101010011011011101010100101010010100100000010111101110101001101101110101001101101111010011011110011011110110110111101001100101010010100100000010111101110101001101101101101101101101111010100110110111010100110110111010100110111100110111101101101111010011001010100101001000000101111011101010011011011101010011011011101010011011110011011110110110111101001100 10 ^ 50更长

类似于整个遗传密码或十亿亿倍的东西,如果您必须流式传输整个内容,那么它太大了,无法读取到内存中,而等待以动态方式将其编码为十六进制的速度太慢,然后才能确定最终的编码。

所以我想知道三件事:

  1. 如果您必须完全阅读某些内容才能将其编码为其他字母。
  2. 如果您这样做,那么为什么会这样。
  3. 如果不这样做,它是如何工作的。

我问的原因是因为看一个像1010101这样的字符串,如果我将其编码为十六进制,则有几种方法:

  1. 一次只输入一个字符,因此除非字母表为1010101,否则它将基本上保持{a, b}的位置,否则它将为abababa。这是最好的情况,因为您不必在内存中读取超过1个字符的字符即可确定编码。但是它将您限制为2个字符的字母。 (任何超过2个字符的字母,我都会感到困惑)
  2. 通过将其转换为整数,然后将其转换为十六进制值。但这需要读取整个值以计算最终(大)整数大小。所以这就是我感到困惑的地方。

我觉得第三种方法(3)是以某种方式读取输入字节的部分块,例如1010然后010,但是如果编码是整数,因为1010 010 = A 2以十六进制表示,而2 = 10不是2 = 010。因此,就像您需要通过在每个块的开头添加一个1来打破它。但是,如果您希望每个块的长度不超过10个十六进制字符,但是却有1000个长0的字符串,那又需要一些其他技巧,例如让编码后的十六进制值告诉您有多少个前面的零,等等。所以这似乎变得很复杂,想知道是否已经建立了一些系统来弄清楚该怎么做。因此出现了以上问题。

例如,假设我想将上述二进制字符串编码为8位字母,例如ASCII。然后我可能有aBc?D4*&((!...。但是将其反序列化为位是一部分,而将位序列化为这是另一部分(这些字符不是映射到上述位示例的实际字符)。

1 个答案:

答案 0 :(得分:0)

  

但是,如果您希望每个块的长度不超过10个十六进制字符,但是您却拥有1000个0的长字符串,那又需要一些其他技巧,例如,让编码后的十六进制值告诉您多少个前面的零等等。所以似乎变得很复杂,想知道是否已经建立了一些系统来弄清楚该怎么做

是的,您过于复杂了。首先,考虑一下长度定义为4的倍数的位字符串,只需将位按4分组并将其重新映射为十六进制数字,就可以用十六进制表示。

raw:   11011110101011011011111011101111
group: 1101 1110 1010 1101 1011 1110 1110 1111
remap: D    E    A    D    B    E    E    F

所以11011110101011011011111011101111 -> DEADBEEF。所有半字节都设置了最高位是由于这样选择一个示例而产生的巧合。 按照定义,将输入分为四个组,然后将每个十六进制数字解码为四个位(如果适用),包括前导零。这就是具有4位倍数的典型哈希码所需的全部内容。

当我们要编码长度可变且不一定是4长的倍数的位串时,问题就开始了,然后某个地方必须有一些填充,并且解码器需要知道有多少填充(以及在哪里填充) ,但位置是您选择的约定)。这就是为什么您的示例如此含糊的原因:它是。需要添加额外的信息来告诉解码器要丢弃多少位。

例如,撇开传输填充位数的机制,我们可以将1010101编码为A5AA5A(甚至更多!)在我们选择用于填充的位置上,无论选择哪种约定,解码器都需要知道填充为1位。为了用位表示,1010101可以被编码为以下任意一种:

x101 0101
101x 0101
1010 x101
1010 101x

x标记在编码器中插入并在解码器中丢弃的位。该位的值实际上并不重要,因为它已被丢弃,因此DA也是一种很好的编码,依此类推。

尽管将填充放在第一个十六进制数字中,但需要知道 length ,所有选择填充位置的选择仍然可以使位字符串进行增量编码,而无需将整个位字符串存储在内存中。 em>前面的位串。

如果您在霍夫曼编码的上下文中询问此问题,则不需要预先计算位字符串的长度,因此必须在末尾进行填充。通常,在字母表中会添加一个额外的符号来表示流的结尾,这通常使得无需显式存储填充位的数量(它们可以是任意数量,但是当它们出现在STOP符号之后时,解码器会自动忽略它们。)