在Ruby中以字符串形式读取二进制文件


263

我需要一种简单的方法来获取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显示文件大小不同,尽管它们非常接近(打开文件可以看到大部分内容完整无缺)。我正在犯一个小错误,还是一种完全不同(但可行)的方式来实现这一目标?


3
那是一个压缩的tar文件(我希望)。没有“线”。请说明您要达到的目标。
Brent.Longborough,

您是要查看压缩数据还是未压缩内容?
David Nehme

因此压缩数据流中的字符将有大约256分之一的概率降落在定义行尾的“ \ n”上,如果也不要期望“ \ r”也可以,请参见下面的答案
Purfideas

此问题应重新命名为“将二进制文件转换为字符串”,因为IO.read否则将是首选答案。
2014年

Answers:


397

首先,您应该以二进制文件形式打开文件。然后,您可以通过一个命令读取整个文件。

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

这将使您获得整个文件的字符串。

之后,您可能想要file.close。如果您不这样做,则在file将其垃圾回收之前,它不会被关闭,因此在打开它时会浪费系统资源。


22
二进制标志仅在Windows上相关,这使文件描述符保持打开状态。File.read(...)更好。
Daniel Huckstep 2011年

如此多的人查找并复制粘贴作为一种单行解决方案,这有什么问题(就像stackoverflow上的很多事情一样)吗?毕竟,它是可行的,这些函数的名称只是ruby库设计人员的任意选择。如果我们只有某种带有同义词的语言……那仍然会以某种方式确切地知道我们在极端情况/模棱两可的情况下想要什么。那我就contents = (contents of file "path to file.txt" as string)
masterxilo 2014年

2
这应该分begin {..open..} ensure {..close..} end块完成
shadowbq

3
@ArianFaurtosh不,这是读取文件的另一种方法-并不意味着它将被视为可执行文件并可以运行!对于简单的“读取”方法,这将是一个令人恐惧的副作用。
马修(Matthew)阅读

1
@David您不能简单地完成以下一线工作吗?contents = File.binread('path-to-file.tar.gz')ApidockFile是的子类IO
瓦斯

244

如果需要二进制模式,则需要用困难的方式做到这一点:

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

如果不是,则更短更甜的是:

s = IO.read(filename)

在ruby 1.9.3+中,IO.read将为您提供一个字符串,该字符串在Encoding.default_external中标有编码。我认为(?)字节将全部与文件中的字节相同,因此并不是完全“不是二进制安全的”,但是如果您要使用二进制编码,则必须对其进行标记。
jrochkind 2014年

如果最重要的是s = File.open(filename, 'rb', &:read)
酥脆

114

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

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

10
这比David Nehme的答案更好,因为文件描述符是有限的系统资源,并且耗尽它们是一个很容易避免的常见问题。
Jeff McCune 2012年

17

在OS X上,这些对我来说都是一样的...在Windows中这可能是多余的“ \ r”吗?

无论如何,您可能会更好:

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

这似乎是最简单的解决方案。
Dishcandanty


10

红宝石有二进制阅读

data = IO.binread(path/filaname)

或低于Ruby 1.9.2

data = IO.read(path/file)

7

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

您可以执行以下操作:

require 'base64'

file_contents = Base64.encode64(tar_file_data)

看一下Base64 Rubydocs以获得更好的主意。


太好了,看起来也可以使用!如果由于某种原因读取二进制内容变酸,我将不得不检查一下。
克里斯·邦奇

0

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

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

要么

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

在cmd中打印每行(文本)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.