【问题标题】:Write array of radix-2 numeric strings to binary file in Ruby将基数 2 数字字符串数组写入 Ruby 中的二进制文件
【发布时间】:2013-05-25 03:48:46
【问题描述】:

我用 Ruby 编写了一个简单的 Huffman 编码。作为输出,我有一个数组,例如:

["010", "1111", "10", "10", "110", "1110", "001", "110", "000", "10", "011"]

我需要在文件中写入,然后读取。我尝试了几种方法:

IO.binwrite("out.cake", array)

我得到一个简单的文本文件,而不是二进制文件。

或者:

File.open("out.cake", 'wb' ) do |output|
  array.each do | byte |
       output.print byte.chr
  end
end

看起来它可以工作,但我无法将它读入数组。

我应该使用哪种编码?

【问题讨论】:

  • 您希望文件包含什么?人物?还是比特?还是 Ruby 数组?还是别的什么?
  • 位。因为我需要更小的文件大小。
  • 答案很可能涉及使用pack

标签: ruby io bindata


【解决方案1】:

我认为您可以像下面的代码一样使用Array#packString#unpack

# Writing
a = ["010", "1111", "10", "10", "110", "1110", "001", "110", "000", "10", "011"]
File.open("out.cake", 'wb' ) do |output|
  output.write [a.join].pack("B*")
end

# Reading
s = File.binread("out.cake")
bits = s.unpack("B*")[0] # "01011111010110111000111000010011"

我不知道您对阅读结果的首选格式,我知道上述方法效率低下。但无论如何,您可以从unpack 的结果中依次取“0”或“1”来遍历您的霍夫曼树。

【讨论】:

  • @IvanKozlov 在这里您可以看到如何将这些位读回字符串。现在您只需使用 Huffman 解码将其拆分为多个片段。
【解决方案2】:

如果你想要位,那么你必须手动进行打包和解包。 Ruby 或任何其他常用语言都不会为您做这件事。

您的数组包含作为字符组的字符串,但您需要构建一个字节数组并将这些字节写入文件。

来自:["010", "1111", "10", "10", "110", "1110", "001", "110", "000", "10", "011"]

您应该构建这些字节:01011111 01011011 10001110 00010011

由于只有四个字节,您可以将它们放入一个 32 位数字 01011111010110111000111000010011,即 5F5B8E13 hex。

您的两个代码示例执行不同的操作。第一个将 Ruby 数组的字符串表示形式写入文件。第二个写入 32 个字节,每个字节为 48 ('0') 或 49 ('1')。

如果你想要位,那么你的输出文件大小应该只有四个字节。

阅读位操作以了解如何实现这一点。


这是一个草稿。 我没有测试它。可能有问题。

a = ["010", "1111", "10", "10", "110", "1110", "001", "110", "000", "10", "011"]

# Join all the characters together. Add 7 zeros to the end.
bit_sequence = a.join + "0" * 7  # "010111110101101110001110000100110000000"

# Split into 8-digit chunks.
chunks = bit_sequence.scan(/.{8}/)  # ["01011111", "01011011", "10001110", "00010011"]

# Convert every chunk into character with the corresponding code.
bytes = chunks.map { |chunk| chunk.to_i(2).chr }  # ["_", "[", "\x8E", "\x13"]

File.open("my_huffman.bin", 'wb' ) do |output|
  bytes.each { |b| output.write b }
end

注意:当字符总数不能被 8 整除时,将添加七个零来处理大小写。没有这些零,bit_sequence.scan(/.{8}/) 将删除剩余的字符。

【讨论】:

  • 你能粘贴一些示例代码吗?对于may数组,如何打包和解包?
  • 基本上哈夫曼码用于压缩或归档。因此,我希望拥有最小大小的文件。你对它的想法?您建议哪种方法?
  • 我添加了一个草稿作为示例。我没有时间仔细测试。
  • 谢谢,你的回答真的很有用。最后一个问题:如何将“my_huffman.bin”读取到初始数组?
  • 看看 M. Shiina 的回答。它甚至比我的还要好。我对 pack("B*") 不太熟悉。
猜你喜欢
  • 2016-05-08
  • 2016-01-15
  • 1970-01-01
  • 2013-05-29
  • 1970-01-01
  • 2020-08-28
  • 1970-01-01
  • 2021-10-27
  • 1970-01-01
相关资源
最近更新 更多