2008-09-25 14 views
256

Ich brauche eine einfache Möglichkeit, eine TAR-Datei zu nehmen und in eine Zeichenfolge umzuwandeln (und umgekehrt). Gibt es eine Möglichkeit, dies in Ruby zu tun? Mein bester Versuch war:Binärdatei als Zeichenfolge in Ruby lesen

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

Ich dachte, dass genug wäre, es in eine Zeichenfolge zu konvertieren, aber dann, wenn ich versuche es so aus, schreiben zurück ...

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

Es isn Es ist dieselbe Datei. Doing ls -l zeigt die Dateien sind von unterschiedlicher Größe, obwohl sie ziemlich nah sind (und das Öffnen der Datei zeigt den größten Teil des Inhalts intakt). Gibt es einen kleinen Fehler, den ich mache oder einen ganz anderen (aber praktikablen) Weg, dies zu erreichen?

+3

Das ist eine gzip-tar-Datei (hoffe ich). Es gibt keine "Linien". Bitte klären Sie, was Sie erreichen möchten. –

+0

versuchen Sie, die komprimierten Daten oder unkomprimierten Inhalt zu sehen? –

+0

so Zeichen in einem komprimierten Datenstrom wird etwa 1 in 256 Chance auf "\ n" landen Ende einer Zeile zu landen, und das ist in Ordnung, wenn es nicht erwartet "\ r" auch, siehe meine Antwort unter – Purfideas

Antwort

380

Zuerst Sie die Datei als Binärdatei öffnen sollte. Dann können Sie die gesamte Datei in einem Befehl lesen.

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

Das wird Ihnen die gesamte Datei in einem String bekommen.

Danach möchten Sie wahrscheinlich file.close. Wenn Sie das nicht tun, wird file nicht geschlossen, bis es Müll-gesammelt wird, so wäre es eine leichte Verschwendung von Systemressourcen, während es geöffnet ist.

+92

Einzeiler: File.open ("Pfad-zu-Datei.tar.gz", "rb"). Lesen – Nobu

+22

Das binäre Flag ist nur unter Windows relevant, und der Dateideskriptor bleibt offen. File.read (...) ist besser. –

+0

Ist etwas falsch mit so vielen Leuten, die das nachschlagen und es als One-Liner-Lösung einfügen (wie so viele Dinge auf stackoverflow)? Schließlich funktioniert es, und der Name für diese Funktionen war nur eine willkürliche Wahl der Ruby-Bibliothek-Designer. Wenn wir nur eine Sprache mit Synonymen hätten ... die irgendwie immer noch genau weiß, was wir in Randfällen/mehrdeutigen Instanzen wollen. Dann würde ich einfach 'contents = (Inhalt der Datei" path to file.txt "als String)'. – masterxilo

4

Sie können wahrscheinlich die TAR-Datei in Base64 kodieren. Base 64 gibt Ihnen eine reine ASCII-Darstellung der Datei, die Sie in einer einfachen Textdatei speichern können. Dann können Sie die TAR-Datei abrufen, indem Sie den Text zurückdecodieren.

Sie tun so etwas wie:

require 'base64' 

file_contents = Base64.encode64(tar_file_data) 

Blick auf die Base64 Rubydocs eine bessere Vorstellung zu bekommen.

+0

Großartig, das sieht aus, als würde es auch funktionieren! Ich muss es überprüfen, wenn aus irgendeinem Grund das Lesen der binären Inhalte sauer wird. –

16

auf os x das sind die gleichen für mich ... könnte das vielleicht extra "\ r" in Windows sein?

in jedem Fall können Sie besser mit sein:

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

'File.read (" e.txt ")' funktioniert gut für mich. – bean5

+0

Dies scheint die einfachste Lösung zu sein. – Dishcandanty

113

Um zu vermeiden, dass die Datei geöffnet bleibt, empfiehlt es sich, einen Block an File.open zu übergeben. Auf diese Weise wird die Datei geschlossen, nachdem der Block ausgeführt wurde.

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

Dies ist eine bessere Antwort als die von David Nehme, da Dateideskriptoren eine endliche Systemressource sind und deren Erschöpfung ein häufiges Problem darstellt, das leicht vermieden werden kann. –

237

Wenn Sie Binär-Modus benötigen, müssen Sie es auf die harte Art und Weise tun:

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

Wenn nicht, kürzer und süßer ist:

s = IO.read(filename) 
+0

Wie ist 'IO.read' nicht binärsicher? –

+0

In Ruby 1.9.3+ gibt IO.read einen String, der mit der Kodierung in Encoding.default_external markiert ist. Ich _think_ (?) Die Bytes werden alle so sein, wie sie in der Datei waren, also ist es nicht genau "nicht binär-sicher", aber Sie müssen es mit der binären Kodierung kennzeichnen, wenn Sie das wollen. – jrochkind

17

wie wäre es offen/Sicherheit schließen.

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

warum nicht eine explizite .close? Wie in der OP-Datei.schließen, wenn Sie fertig sind? – Joshua

+2

Datei.open() {| Datei | Block} wird automatisch geschlossen, wenn der Block beendet wird. http://ruby-doc.org/core-1.9.3/File.html#method-c-open – Alex

+12

Dies ist identisch mit [Aaron Hinnis Antwort] (http://stackoverflow.com/a/131096/ 215168), die 2008 veröffentlicht wurde (außer dass die Datei- und Variablennamen von OP nicht verwendet wurden) ... –

0

Wenn Sie die TAR-Datei von Base64 (und speichern sie in einer Textdatei) kodieren, können Sie

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

oder

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

jeweils zum Drucken verwenden (Text) Zeile im cmd.

5

Rubin hat Binär-Lese

data = IO.binread(path/filaname) 

oder wenn weniger als Rubin 1.9.2

data = IO.read(path/file)