【发布时间】:2011-08-27 19:28:19
【问题描述】:
我有一种情况需要在 Ruby 中将二进制值转换为十六进制。我的情况如下:
当bin = "0000111"时,我的输出应该是:hex = "07"。
当bin = "010001111"时,我的输出应该是:hex = "08f"。
有人可以帮我解决这个问题吗?提前致谢。
【问题讨论】:
我有一种情况需要在 Ruby 中将二进制值转换为十六进制。我的情况如下:
当bin = "0000111"时,我的输出应该是:hex = "07"。
当bin = "010001111"时,我的输出应该是:hex = "08f"。
有人可以帮我解决这个问题吗?提前致谢。
【问题讨论】:
怎么样:
>> "0x%02x" % "0000111".to_i(2) #=> "0x07"
>> "0x%02x" % "010001111".to_i(2) #=> "0x8f"
编辑:如果您不希望输出为0x..,而只是0..,则省略格式字符串中的第一个x。
【讨论】:
"0x%02x"%"1".to_i(2) #=> "0x01".
def bin_to_hex(s)
s.each_byte.map { |b| b.to_s(16).rjust(2,'0') }.join
end
我在这里找到的(零填充修改):
http://anthonylewis.com/2011/02/09/to-hex-and-back-with-ruby/
【讨论】:
'1111'.each_byte.map { |b| b.to_s(16) }.join => "31313131"(我想要 "f" 或类似的东西。)
'1111' 有四个字节,每个字节的值为49(即ASCII 值)。十进制的 49 是十六进制的 31。从问题所谈论的意义上讲,您没有“二进制”值。您有一个包含 ASCII 字符 '1' 和 '0' 的字符串。
String#to_i 和 Integer#to_s 都采用一个可选的整数参数来指定基数。因此,您可以使用基数 2 将二进制字符串转换为整数,然后使用基数 16 将该整数转换回字符串。
【讨论】:
String#%(又名sprintf)而不是to_s 来适当地格式化数字 - 使用%02x 将数字格式化为填充到2 位的十六进制数字使用 0。但是,如果您想要 16 以外的基数(如果您使用 d 而不是 x,则为 10)这不起作用,因为 % 不允许您选择任意基数。或者,您可以使用to_s 后跟String#rjust,它适用于任意基数和填充字符。
您可以使用unpack 方法将目标指向十六进制的字符串
def bin_to_hex(binary_string)
binary_string.unpack('H*').first
end
参考:https://apidock.com/ruby/String/unpack
我发现它比上面列出的解决方案干净得多。
【讨论】:
如上所述,@Michael Kohl 最简单的方法是使用操作定义方法
# if you don't want the output to be 0x.. but just 0.. leave out the first x in the format string.
def self.bin_to_hex(string)
"0x%02x" % "#{string}".to_i(2)
end
并使用这样的方法
string = "00011110"
puts bin_to_hex(string)
=> 0x1e
请记住,这些仍然是 ASCII 表示,以防您想对其进行编码并将字节作为 HEX(通过 UDP 或低级协议发送)发送:
value = self.bin_to_hex(value)
bytes = [value]
bytes.pack('H*' * bytes.size)
【讨论】: