2017-07-07 3 views
1

Hier ist ein Hash, den ich in einer Datei speichern, um später gelesen zu werden.Ein Hash von einer Datei auf der Festplatte lesen

my_hash = {-1 => 20, -2 => 30, -3 => 40} 
File.open("my_file.txt", "w") { |f| f.write my_hash } 
#how it looks opening the text file 
{-1 => 20, -2 => 30, -3 => 40} 

Wenn ich gehe, es zu lesen, ist, wo mein Problem ist. (Code finden Sie getrennt von oben)

my_hash = File.foreach("my_file.txt") { |f| print f } 
p my_hash 
#=> {-1 => 20, -2 => 30, -3 => 40}nil 

dass nil Verwirrungen der Rest meines code..not bis sicher, wie der, wenn loszuwerden. Nur aus Gründen der Klarheit der Rest des Codes ...

back_up_hash = {-1 => 20} 
if my_hash.nil? 
    my_hash = back_up_hash 
end 

Das kleine nil macht immer my_hash gleich back_up_hash. Ich brauche das .nil? nur für den Fall, dass die Datei nicht den Hash hat, sonst wird das Problem nur weiter unten gedrückt.

Ich habe auch versucht (schlürfen? .. es ist eine kleine Datei) lesen Sie die Datei wie folgt ....

my_hash = File.read("my_file.txt") { |f| print f } 
p my_hash 
=> "{-1 => 20, -2 => 30, -3 => 40}" 
# not sure how to get it out of string form...and I have searched for it. 
+1

Ich bin nicht mit Ruby vertraut, aber ich bin ziemlich sicher, dass Sie das Objekt in eine Datei serialisieren müssen, anstatt nur die Datenstrukturdarstellung zu schreiben. Wenn ich raten müsste, würde ich sagen, das ist Teil Ihres Problems. –

+0

Sie könnten daran interessiert sein, mit dem ['Marshal'-Modul] (https://ruby-doc.org/core-2.2.2/Marshal.html) native Ruby-Objekte auf Festplatte zu speichern und sie schnell später zu laden. – Phrogz

+0

@ Benutzer. Ja, dieser Thread hat eine funktionierende Antwort für mich .... und ich habe es vorher gesehen. Leider bin ich ein wenig überfordert und wenn die Antwort für meine Situation nicht annähernd perfekt ist, geht sie an mir vorbei. Danke, dass Sie auf diesen Link hingewiesen haben. Marshal sieht wie eine gute Lösung aus. – melee

Antwort

1

Die richtige Methode, um einfache Datenstrukturen in einer Datei zu speichern, besteht darin, sie zu serialisieren. In diesem speziellen Fall mit JSON ist wahrscheinlich eine gute Wahl:

# save hash to file: 
f.write MultiJson.dump(my_hash) 

# load it back: 
p MultiJson.load(file_contents) 

Beachten Sie, dass JSON nur in der Lage zu serialisiert einfach, integrierten Datentypen (Strings, Zahlen, Arrays, Hashes und dergleichen). Sie können keine benutzerdefinierten Objekte auf diese Weise serialisieren und deserialisieren, ohne dass zusätzliche Arbeit erforderlich ist.

Wenn Sie nicht MultiJson haben, versuchen Sie es stattdessen mit JSON.

+0

Ich schätze diese Antwort mehr ein paar Tage später. Ich endete letztendlich mit Json. – melee

1

Sie die eval Methode auf der Saite (source)

nutzen könnten
eval("{-1 => 20, -2 => 30, -3 => 40}") 
=> {-1 => 20, -2 => 30, -3 => 40} 
0

Wenn Sie eine Datei auf der Festplatte, deren Inhalt {-1 => 20, -2 => 30, -3 => 40} sind zu nehmen und einen Hash daraus machen, Sie wollen:

hash_str = File.read('my_file.txt') 
my_hash = eval(hash_str) # Treat a string like Ruby code and evaluate it 

# or, as a one-liner 
my_hash = eval(File.read('my_file.txt')) 

Was Sie taten in der Datei zu lesen und es auf den Siebdrucken, eine Zeile nach der anderen. Der Befehl 'print' transformiert die Daten nicht, und die Methode foreach ordnet die Daten, die sie zu Ihrem Block liefert, nicht in ein Ergebnis ein. Deshalb erhalten Sie nil für Ihre my_hash.

Wie ich in einem Kommentar zu empfehlen, wenn Sie ein Ruby-Objekt (wie ein Hash) haben und Sie müssen es auf der Festplatte speichern und später laden, können Sie das Marshal Modul (eingebaut in Rubin) verwenden möchten:

$ irb 
irb(main):001:0> h = {-1 => 20, -2 => 30, -3 => 40} 
#=> {-1=>20, -2=>30, -3=>40} 
irb(main):002:0> File.open('test.marshal','wb'){ |f| Marshal.dump(h, f) } 
#=> #<File:test.marshal (closed)> 

$ irb  # later, a new irb session with no knowledge of h 
irb(main):001:0> h = File.open('test.marshal'){ |f| Marshal.load(f) } 
#=> {-1=>20, -2=>30, -3=>40} 
+0

Ich habe Eval nie versucht, weil ich lese, dass es gefährlich ist. Der eine Liner funktionierte perfekt. my_hash wird Benutzereingaben haben, aber immer Ganzzahlen. Weißt du das, würdest du mich zur Marshall-Lösung lenken oder ist das okay? – melee

+0

Muss ich eval manuell schließen? – melee

+0

@Melee: Nein, du musst Eval nicht schließen, was auch immer das bedeuten würde. Die Datei selbst wird nach dem Lesen automatisch geschlossen. Bitte verwenden Sie nicht die 'eval' Lösung, es ist gefährlich, besonders bei Benutzereingaben. –

0

ich habe mit diesen 2 einfachen Methoden hatten Erfolg:

def create_json_copy 
    File.open("db/json_records/stuff.json","w") do |f| 
    f.write("#{@existing_data.to_json}") 
    end 
end 

def read_json_copy 
    @json = JSON.parse(File.read("db/json_records/stuff.json")).as_json.with_indifferent_access 
    @json.each do |identifier,record| 
    existing_record = Something.find_by(some_column: identifier) 
    if !existing_record 
     Something.create!(record.except(:id).except(:created_at).except(:updated_at)) 
    end 
    end 
end 

Anmerkung: @existing_data ist ein Ruby-Hash als { some_identifier: record_objet, ... } organisiert. Ich rufe .to_json darauf an, bevor ich es in Datei schreibe, und dann beim Lesen I JSON.parse es gefolgt von .as_json, with_indifferent_access ist hier nicht wirklich erforderlich, so dass Sie es ausziehen können, solange Sie die Symbole innerhalb der excepts ersetzen.

Verwandte Themen