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
これはgzipされたtarファイルです(私はそう思います)。「線」はありません。Plsは、達成しようとしていることを明確にします。
Brent.Longborough 2008

圧縮データまたは非圧縮コンテンツを確認しようとしていますか?
David Nehme

したがって、圧縮されたデータストリームの文字は、行の終わりを定義する「\ n」に
着く

この質問は、「バイナリファイルを文字列に変換する」というタイトルに変更する必要がありIO.readます。
イアン

回答:


397

まず、ファイルをバイナリファイルとして開く必要があります。その後、1つのコマンドでファイル全体を読み取ることができます。

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 14

2
これはbegin {..open..} ensure {..close..} endブロック単位で行う必要があります
shadowbq

3
@ArianFaurtoshいいえ、それはファイルを読み取る別の方法です-それが実行可能ファイルとして扱われ、実行されるという意味ではありません!これは、単純な「読み取り」メソッドの恐ろしい副作用になります。
Matthewが

1
@Davidは、次のワンライナーを簡単に実行できませんでしたか?apidockをcontents = File.binread('path-to-file.tar.gz')参照してください。 のサブクラスです。FileIO
vas

244

バイナリモードが必要な場合は、難しい方法で行う必要があります。

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

そうでない場合、短くて甘いのは:

s = IO.read(filename)

Ruby 1.9.3以降では、IO.readはEncoding.default_externalのエンコーディングでマークされた文字列を提供します。私(?)バイトはすべてファイル内のとおりであると思うので、厳密に「バイナリセーフではない」わけではありませんが、それが必要な場合は、バイナリエンコーディングでタグ付けする必要があります。
jrochkind 14

短さと甘さが本質的なものである場合、アンパサンド記号のprocトリックが提供しますs = File.open(filename, 'rb', &:read)
Epigene

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

17

開閉の安全性についてはどうですか。

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

なぜ明示的な.closeではないのですか?OPファイルのように。完了したら閉じる?
ジョシュア

2
File.open(){| file | block}は、ブロックが終了すると自動的に閉じます。 ruby-doc.org/core-1.9.3/File.html#method-c-open
Alex

14
これは、2008年に投稿されたAaron Hinniの回答と同じです(OPのファイル名と変数名を使用しないことを除く)...
Abe Voelker

10

Rubyにはバイナリ読み取りがあります

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ご覧ください


これでうまくいくようです。何らかの理由でバイナリコンテンツの読み取りがうまくいかない場合は、チェックする必要があります。
Chris Bunch

0

tarファイルをBase64でエンコードして(プレーンテキストファイルに保存して)いる場合は、次のコマンドを使用できます。

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

または

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

cmdの各(テキスト)行を印刷します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.