Ruby的包装和解包解释

Gad*_*i A 8 ruby pack

甚至阅读标准文档后,我仍然无法理解如何Ruby的Array#packString#unpack准确的工作.这是导致我最麻烦的例子:

irb(main):001:0> chars = ["61","62","63"]
=> ["61", "62", "63"]
irb(main):002:0> chars.pack("H*")
=> "a"
irb(main):003:0> chars.pack("HHH")
=> "```"
Run Code Online (Sandbox Code Playgroud)

我希望这两个操作都返回相同的输出:"abc".他们每个人都以不同的方式"失败"(因为我可能期待错误的事情,所以不是真的失败).所以有两个问题:

  1. 这些产出背后的逻辑是什么?
  2. 如何实现我想要的效果,即将十六进制数字序列转换为相应的字符串.更好的是 - 给定一个整数n,如何将其转换为与文本文件相同的字符串,将其视为数字(例如,在十六进制编辑器中)等于n?

the*_*Man 10

我们今天早上正在研究类似的问题.如果数组大小未知,您可以使用:

ary = ["61", "62", "63"]
ary.pack('H2' * ary.size)
=> "abc"
Run Code Online (Sandbox Code Playgroud)

您可以使用以下方法撤消它

str = "abc"
str.unpack('H2' * str.size)
=> ["61", "62", "63"]
Run Code Online (Sandbox Code Playgroud)

  • @theTinMan啊,我现在看到了.这是一个文档错误.Ruby的`pack`是在Perl之后建模的,perldoc是明确的,计数值对AaZHhBbPp有不同的含义. (2认同)

Eri*_*ker 5

这种Array#pack方法非常神秘.解决问题(2),我能够通过这样做让你的例子工作:

> ["61", "62", "63"].pack("H2H2H2")
=> "abc" 
Run Code Online (Sandbox Code Playgroud)

有关类似示例,请参阅Ruby文档.这是一种更通用的方法:

["61", "62", "63"].map {|s| [s].pack("H2") }.join
Run Code Online (Sandbox Code Playgroud)

这可能不是解决问题的最有效方法; 我怀疑有更好的方法,但它有助于了解你开始使用什么样的输入.

#pack方法对于其他语言是常见的,例如Perl.如果Ruby的文档没有帮助,您可以在其他地方查阅类似的文档.


小智 5

'H'弦乐指令Array#pack说,数组的内容应该被解释为十六进制字符串的蚕食.

在第一个示例中,您提供了:

irb(main):002:0> chars.pack("H*")
=> "a"
Run Code Online (Sandbox Code Playgroud)

你告诉你将数组的第一个元素打包成一个十六进制字符串的半字节(半字节)序列:0x61在这种情况下,它对应于'a'ASCII字符.

在第二个例子中:

irb(main):003:0> chars.pack("HHH")
=> "```"
Run Code Online (Sandbox Code Playgroud)

你要告诉他们将数组的3个元素打包成半字节(在这种情况下是高位):0x60对应于'`'ASCII字符.0x01由于缺少"aTemplateString"的"2"或"*"修饰符,低部分或第二个半字节()"丢失".

你需要的是:

chars.pack('H*' * chars.size)
Run Code Online (Sandbox Code Playgroud)

为了打包数组中所有元素的所有半字节,就好像它们是十六进制字符串一样.

'H2' * char.size如果数组元素仅表示1字节的十六进制字符串,则只能正常工作.

这意味着类似的东西chars = ["6161", "6262", "6363"]将是不完整的:

2.1.5 :047 > chars = ["6161", "6262", "6363"]
 => ["6161", "6262", "6363"] 
2.1.5 :048 > chars.pack('H2' * chars.size)
 => "abc" 
Run Code Online (Sandbox Code Playgroud)

而:

2.1.5 :049 > chars.pack('H*' * chars.size)
 => "aabbcc"
Run Code Online (Sandbox Code Playgroud)