2

我需要一个任意长度的二进制字符串的数字表示。这个看似微不足道的任务,却意外地变得复杂起来。到目前为止我能想到的最好的是

string.unpack('H*')[0].to_i(16)

但是这个操作缺乏可逆性,因为 unpack 可能会在最高半字节返回前导零:

['ABC'].pack('H*') == ['0ABC'].pack('H*') # false

现在我需要检查从整数转换后是否有偶数个半字节,如果需要则用零填充等。这一切都很好而且很清楚,但我简直不敢相信这一定如此复杂。

更新示例:

s = "\x01\x1D\x9A".force_encoding 'binary' # "\x01\x1D\x9A"
s.unpack('H*') # ["011d9a"]
s.unpack('H*')[0].to_i(16) # 73114

现在让我们解码:

s.unpack('H*')[0].to_i(16).to_s(16) # "11d9a" — notice that leading zero is gone
[s.unpack('H*')[0].to_i(16).to_s(16)].pack('H*') # "\x11\xD9\xA0"
[s.unpack('H*')[0].to_i(16).to_s(16)].pack('H*') == s # false, obviously

换句话说,我们未能解码到与开始时相同的值。

4

1 回答 1

0

不幸的是,我对 Ruby 的了解为零,但有一个可以检查的想法......

可能是 .to_s(16) 方法转换为具有不同默认编码的字符串,当您在 .pack('H*') 之后进行字符串比较时,这可能很重要?可能这会起作用: [s.unpack('H*')[0].to_i(16).to_s(16)].pack('H*').force_encoding 'binary' == s

否则很难想象带前导零的半字节如何转换为与相同字符串字节不同但从不带零的十六进制半字节转换的字符串字节。

于 2012-04-18T15:52:42.580 回答