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

Reading a hash from a file on disk

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

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.

您可以在字符串 (source)

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

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

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

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

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

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

如果你想在磁盘上获取一个内容为 {-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 方法不会将它产生的数据映射到您的块到任何结果。这就是为什么您的 my_hash.

得到 nil

正如我在评论中所建议的那样,如果您有一个 Ruby 对象(如哈希)并且您需要将其保存到磁盘并稍后加载它,您可能需要使用 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}

我已经通过这两种简单的方法取得了成功:

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 哈希。我在将它写入文件之前调用 .to_json 然后在读取时我 JSON.parse 它后跟 .as_json,这里不需要 with_indifferent_access 所以你可以接受它只要您替换 excepts.

中的符号即可关闭