红宝石字符串#unpack

Posted

技术标签:

【中文标题】红宝石字符串#unpack【英文标题】:Ruby String#unpack 【发布时间】:2013-02-16 12:40:54 【问题描述】:

我有一个由 3 个字符串组成的打包字符串,它的组合方式使我有一个整数,指定下一个项目的字节长度,然后是那个项目的字节,然后是下一个项目的字节大小,等等,好像有人做了:

[a.bytesize, a, b.bytesize, b, c.bytesize, c].pack("na*na*na*")

我怎样才能以简单的方式正确解压?这个问题的 Perl 解决方案是:

my($a, $b, $c) = unpack("(n/a*)3", $data)

对于 ruby​​,它在 unpack 中显然不支持 '/' 和括号,我正在使用类似的东西:

vals = []
3.times do
  size = data.unpack("n").first
  data.slice!(0, 2)
  vals << data.unpack("a#size").first
  data.slice!(0, size)
end

有没有更简单的方法?

【问题讨论】:

除非有人找到一个简单的解决方案,否则我会考虑提出一个功能请求来扩展 ruby​​ 的问题跟踪器上的解包,如果实现获得一些 Perl 功能似乎可能会有用 【参考方案1】:

恕我直言,它不像 PERL 中那么容易,但这是我可以建议的一些解决方案。

unpacked = []
a, b, c = *unpacked << data.slice!(0, data.slice!(0, 2).unpack('S>').first) \
           until data.empty? 

【讨论】:

【参考方案2】:

我没有看到像 Perl 解决方案那样容易做到这一点的方法(并且同意提交功能请求以将其添加到 Ruby 的打包/解包实现中会很好),但我至少可以提供如果有帮助,可以用更少的行来解决:

vals = []
until data.empty?
  vals << data.slice!(0, data.slice!(0,2).unpack('n').first.to_i).unpack("a*").first
end

【讨论】:

【参考方案3】:

如果您需要任何严肃的二进制数据处理,这里有一个很好的解决方案: http://bindata.rubyforge.org/ 我认为你应该使用它,而不是伪造 unpacks un running loops。

您当然可以提交功能请求并等待其实施, 但我建议您改用 bindata gem,这是一种更强大的 IMO 解决方案。

【讨论】:

以上是关于红宝石字符串#unpack的主要内容,如果未能解决你的问题,请参考以下文章

在 struct.unpack 格式字符串中间切换字节顺序

Perl 中 unpack 结合 join 的性能

Unpack() 在不同的机器上提供不同的结果

我可以使用 Perl 的 unpack 将字符串分解为 vars 吗?

pyextend库-unpack列表集合字符串解包函数

perl中的pack与unpack