【问题标题】:Read binary file as string in Ruby在Ruby中将二进制文件作为字符串读取
【发布时间】:2010-09-12 22:57:23
【问题描述】:

我需要一种简单的方法来获取 tar 文件并将其转换为字符串(反之亦然)。有没有办法在 Ruby 中做到这一点?我最好的尝试是这样的:

file = File.open("path-to-file.tar.gz")
contents = ""
file.each {|line|
  contents << line
}

我认为将其转换为字符串就足够了,但是当我尝试像这样将其写回时...

newFile = File.open("test.tar.gz", "w")
newFile.write(contents)

这不是同一个文件。执行ls -l 显示文件大小不同,尽管它们非常接近(打开文件会显示大部分内容完好无损)。我是否犯了一个小错误或完全不同(但可行)的方法来完成此操作?

【问题讨论】:

  • 这是一个 gzip 压缩的 tar 文件(我希望如此)。没有“线”。请澄清您要实现的目标。
  • 您是要查看压缩数据还是未压缩内容?
  • 所以压缩数据流中的字符将有大约 256 分之一的机会登陆定义行尾的“\n”,如果它不期望“\r”也可以,请看下面我的回答
  • 这个问题应该重新命名为“Convert binary file to string”,否则IO.read将是首选答案。

标签: ruby string file-io


【解决方案1】:

首先,您应该将文件作为二进制文件打开。然后,您可以在一个命令中读取整个文件。

file = File.open("path-to-file.tar.gz", "rb")
contents = file.read

这会让你得到一个字符串中的整个文件。

之后,您可能想file.close。如果你不这样做,file 在被垃圾回收之前不会被关闭,所以在它打开时会稍微浪费系统资源。

【讨论】:

  • 二进制标志仅在 Windows 上相关,这会使文件描述符保持打开状态。 File.read(...) 更好。
  • 这么多人查找并复制粘贴作为单行解决方案有什么问题吗(就像 stackoverflow 上的很多东西一样)?毕竟,它可以工作,而且这些函数的名称只是 ruby​​ 库设计者的任意选择。如果我们有一些带有同义词的语言......它仍然以某种方式确切地知道我们在边缘情况/模棱两可的情况下想要什么。那我就contents = (contents of file "path to file.txt" as string)
  • 这应该在begin {..open..} ensure {..close..} end 块中完成
  • @ArianFaurtosh 不,这是读取文件的另一种方法——这并不意味着它将被视为可执行文件并运行!对于简单的“读取”方法来说,这将是一个可怕的副作用。
  • @David 你不能简单地做以下单行吗? contents = File.binread('path-to-file.tar.gz')apidockFileIO 的子类。
【解决方案2】:

如果您需要二进制模式,则需要努力:

s = File.open(filename, 'rb') { |f| f.read }

如果没有,更短更甜的是:

s = IO.read(filename)

【讨论】:

  • 在 ruby​​ 1.9.3+ 中,IO.read 将为您提供一个标有 Encoding.default_external 中编码的字符串。我认为(?)字节都将与文件中的一样,所以它不完全是“不是二进制安全的”,但如果是这样的话,你必须用二进制编码标记它你想要的。
  • 如果短和甜是本质,& 符号 proc 技巧给出s = File.open(filename, 'rb', &amp;:read)
【解决方案3】:

为避免文件保持打开状态,最好将块传递给 File.open。这样,文件将在块执行后关闭。

contents = File.open('path-to-file.tar.gz', 'rb') { |f| f.read }

【讨论】:

  • 这是一个比 David Nehme 更好的答案,因为文件描述符是有限的系统资源,耗尽它们是一个很容易避免的常见问题。
【解决方案4】:

一些打开/关闭安全性怎么样。

string = File.open('file.txt', 'rb') { |file| file.read }

【讨论】:

【解决方案5】:

在 os x 上这些对我来说是一样的......这可能是 windows 中额外的“\r”吗?

在任何情况下,你可能会更好:

contents = File.read("e.tgz")
newFile = File.open("ee.tgz", "w")
newFile.write(contents)

【讨论】:

  • 这似乎是最简单的解决方案。
【解决方案6】:

Ruby 具有二进制读取功能

data = IO.binread(path/filaname)

或者如果低于 Ruby 1.9.2

data = IO.read(path/file)

【讨论】:

  • 这是 Ruby 1.9.2+ 的正确答案。
【解决方案7】:

您可能可以在 Base64 中对 tar 文件进行编码。 Base 64 将为您提供文件的纯 ASCII 表示,您可以将其存储在纯文本文件中。然后,您可以通过将文本解码回来来检索 tar 文件。

你做这样的事情:

require 'base64'

file_contents = Base64.encode64(tar_file_data)

查看 Base64 Rubydocs 以获得更好的想法。

【讨论】:

  • 太好了,这看起来也可以!如果由于某种原因读取二进制内容变坏,我将不得不检查它。
【解决方案8】:

Ruby 1.9+ 具有IO.binread(参见@bardzo's answer)并且还支持将编码作为选项传递给IO.read

  • Ruby 1.9

    data = File.read(name, {:encoding => 'BINARY'})
    
  • Ruby 2+

    data = File.read(name, encoding: 'BINARY')
    

(请注意,在这两种情况下,'BINARY' 都是 alias 对应于 'ASCII-8BIT'。)

【讨论】:

    【解决方案9】:

    如果您可以通过 Base64 对 tar 文件进行编码(并将其存储在纯文本文件中),则可以使用

    File.open("my_tar.txt").each {|line| puts line}
    

    File.new("name_file.txt", "r").each {|line| puts line}
    

    打印 cmd 中的每一行(文本)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-09
      • 1970-01-01
      • 2014-06-18
      • 1970-01-01
      • 2011-03-12
      • 2013-09-26
      • 1970-01-01
      相关资源
      最近更新 更多