十六进制字符串表示为十六进制

时间:2018-05-18 14:07:01

标签: ruby

我目前正在使用UDP数据包,我需要制作和发送自定义数据。因为我更容易阅读我使用表示十六进制值的字符串。我有这样的事情:

a = "12"
b = "15"
header = "c56b4040003300" + a + "800401" + b + "90000000"

现在,我想要做的是将我的头变量转换为十六进制(但不包含头中每个字符的十六进制值)。这意味着如果我在一个文件中编写我的头变量并用十六进制编辑器打开它,我想看看

c5 6b 40 40 00 33 00 12 80 04 01 15 90 00 00 00

我对红宝石知之甚少,到目前为止我找不到办法。 pack函数将hexa中的字符转换为十六进制值,而不是十六进制字符串表示。做一些像

这样的事情
header = "\xc5\x6b\x40\x40\x00\x33\x00\x" + a + "\x80\x04\x01\x" + b + "\x90\x00\x00\x00"

会给我一个错误,说“无效的十字转义”(这是有意义的)。 因此,如果您有解决此问题的方法,请告诉我(如果可能,不使用任何外部库)

2 个答案:

答案 0 :(得分:2)

require 'strscan'
s = StringScanner.new('hexstring here')
s.scan(/../).map { |x| x.hex.chr }.join

答案 1 :(得分:2)

String#to_i采用一个可以做你想做的基本参数:

["c56b4040003300", a, "800401", b, "90000000"].join.to_i(16)

但将数据表示为大整数可能没有意义。如果您只想要一大块二进制数据,可以将所有内容连接在一起并使用Array#pack

[["c56b4040003300", a, "800401", b, "90000000"].join].pack('H*')

或者您可以打包单个组件并连接结果:

["c56b4040003300", a, "800401", b, "90000000"].map { |s| [s].pack('H*') }.join

或者你可以在整个程序中使用一个字节数组:

bytes = "c56b4040003300".scan(/../)
bytes << a
bytes.concat "800401".scan(/../)
bytes << b
bytes.concat "90000000".scan(/../)
bytes.unpack('H*' * bytes.size)

希望有所帮助!