2017-07-07 134 views
1

下面是一个哈希值,我将其保存到文件中供以后阅读。从磁盘上的文件中读取哈希值

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} 

当我去读它时,是我的问题所在。 (下面的代码是从顶部分开)

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

nil弄乱我的code..not知道如何其余摆脱如果。只是为了清晰起见,其余代码...

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

那个小nil总是让my_hash等于back_up_hash。我需要.nil?以防万一文件没有散列,否则问题会进一步下移。

我也试着阅读(啜食?..它是一个小文件)这样的文件....

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

我不熟悉Ruby,但我很肯定你必须将对象序列化到一个文件,而不是只写数据结构表示。如果我不得不猜测,我会说这是你的问题的一部分。 –

+0

您可能有兴趣使用['Marshal'模块](https://ruby-doc.org/core-2.2.2/Marshal.html)将本地Ruby对象转储到磁盘并在以后快速加载它们。 – Phrogz

+0

@用户。是的,该线程对我来说确实有一个可行的答案......我之前就看到了它。不幸的是,我有点不知所措,如果答案对我的情况来说不太理想,它会让我失望。感谢您指出该链接。元帅看起来是一个很好的解决方案。 – melee

回答

1

将简单数据结构保存到文件的正确方法是对它们进行序列化。在这种特殊情况下,使用JSON可能是一个不错的选择:

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

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

请记住,JSON是只能够序列简单,内置的数据类型(字符串,数字,数组,哈希和类似)。您将无法以这种方式序列化和反序列化自定义对象,而无需额外的工作。

如果您还没有MultiJson,请使用JSON来代替它。

+0

我更感谢这个答案更多的几天后。我完全使用Json。 – melee

1

你可以使用eval方法的字符串(source

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

如果你想利用在磁盘上是{-1 => 20, -2 => 30, -3 => 40}并从中散,你想其内容的文件:

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')) 

你在做什么在文件中读取并打印到屏幕上,一次一行。 'print'命令不会转换数据,并且foreach方法不会将其生成的数据映射到您的数据块中。这就是为什么你得到nil为您的my_hash。如果你有一个Ruby对象(比如一个Hash),你需要将它保存到磁盘并稍后加载,你可能需要使用Marshal模块(内置于Ruby):

$ 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

我从来没有尝试eval,因为我一直在阅读它是危险的。尽管如此,单线纸还是很完美的。 my_hash将有用户输入,但始终是整数。知道这一点,你会引导我走向马歇尔解决方案吗? – melee

+0

我是否必须手动关闭eval? – melee

+0

@melee:不,你不需要关闭eval,不管那意味着什么。文件本身在读取后自动关闭。尽管如此,请不要使用'eval'解决方案,这很危险,特别是在用户输入时。 –

0

我已经成功与这些2点简单的方法:

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 

注:@existing_data是组织为{ some_identifier: record_objet, ... }一个Ruby的Hash。在将它写入文件之前,我将它称为.to_json,然后在读取我之后之后是.as_jsonwith_indifferent_access在这里并不是真的需要,因此只要您替换excepts内的符号,就可以关闭它。