在Ruby中将二进制值转换为十六进制

9

我有一个情况需要在Ruby中将二进制值转换为十六进制。我的情况如下:

bin = "0000111"时,我的输出应该是:hex = "07"

bin = "010001111"时,我的输出应该是:hex = "08f"

有人能帮助我如何做到这一点吗?谢谢提前。

5个回答

14

如何尝试:

>> "0x%02x" % "0000111".to_i(2) #=> "0x07"
>> "0x%02x" % "010001111".to_i(2) #=> "0x8f"

编辑:如果你不想要输出为 0x.. 而只想要 0..,那么在格式化字符串中省略第一个 x

注意: 本翻译中的 "leave out" 翻译为 "省略",意为在格式化字符串中不包含该字符。


当我传递一个单一的二进制位'1'时,它会转换为001。但是在十六进制中它不应该转换为'1'吗? - uptownhr
("0%02x" % binary.to_i(2)) #=> "001" - uptownhr
"0x%02x"%"1".to_i(2) #=> "0x01" =>"0x%02x"%"1".to_i(2) #=> "0x01" - Michael Kohl

11

我不知道人们是怎么说它能工作的!对于我来说,使用 Ruby 4.1,它会返回:'1111'.each_byte.map { |b| b.to_s(16) }.join => "31313131"(而我想要的是 "f" 或类似的东西)。 - Djunzu
@Djunzu 你说的是另一件事。字符串'1111'有四个字节,每个字节的值为49(即ASCII值)。十进制中的49在十六进制中是31。你没有一个像问题所说的那样的“二进制”值。你有一个包含ASCII字符'1''0'的字符串。 - Ryan
@Djunzu 实际上,算了吧。我刚刚意识到你是对的,而且答案中使用了“二进制”的错误含义。 - Ryan

5

String#to_iInteger#to_s都可以接受一个可选的整数参数,指定基数。因此,您可以使用基数2将二进制字符串转换为整数,然后使用基数16将该整数转换回字符串。


1
嘿,感谢您的回复。就像您所说的,如果我使用“11111”.to_i(2).to_s(16),它会给我“1f”,但是如果我使用“01111”.to_i(2).to_s(16),它只会给我“f”,但我想要“0f”。 - sundar
2
@sundar:你可以使用 String#%(又称为sprintf)而不是 to_s 来适当地格式化数字,使用 %02x 将数字格式化为用0填充的两位十六进制数。但是如果您想要除16(或者使用 d 而不是 x 的10)以外的其他基数,则无法使用 % 选择任意基数。或者,您可以使用 to_s 后跟 String#rjust,它可以与任意基数和填充字符一起使用。 - sepp2k

4
您可以在字符串上使用unpack方法,将目标指向十六进制。
def bin_to_hex(binary_string)
  binary_string.unpack('H*').first
end

参考:https://apidock.com/ruby/String/unpack

我认为这个方案比上面列出的解决方案更加简洁。


0
如@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)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接