从磁盘上的文件中读取哈希

时间:2017-07-07 23:01:07

标签: ruby high-availability

这是我保存到文件以便以后读取的哈希。

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弄乱了我的其余代码......不知道如何摆脱if。为了清楚起见,其余代码......

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.

4 个答案:

答案 0 :(得分:3)

您可以在字符串(source

上使用eval方法
eval("{-1 => 20, -2 => 30, -3 => 40}")
=> {-1 => 20, -2 => 30, -3 => 40}

答案 1 :(得分:1)

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

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

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

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

如果您没有MultiJson,请尝试使用JSON

答案 2 :(得分: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}

答案 3 :(得分:0)

我用这两种简单的方法取得了成功:

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,然后在阅读JSON.parse时,它后跟.as_jsonwith_indifferent_access在这里真的不需要,所以你可以把它当作只要替换excepts内的符号。