我需要一个任意长度的二进制字符串的数字表示。这个看似微不足道的任务,却意外地变得复杂起来。到目前为止我能想到的最好的是
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
换句话说,我们未能解码到与开始时相同的值。