从磁盘上的文件中读取哈希
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
.
中的符号即可关闭
这是我保存到文件中供以后读取的哈希值。
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
.