如何将任意 Ruby 对象保存到磁盘并在必要时将其读回? [关闭]
Posted
技术标签:
【中文标题】如何将任意 Ruby 对象保存到磁盘并在必要时将其读回? [关闭]【英文标题】:How can I save an arbitrary Ruby object to the disk and read it back when necessary? [closed] 【发布时间】:2013-11-30 04:52:30 【问题描述】:我想将 Ruby 集或哈希保存到磁盘,并在必要时从文件中返回。我该怎么做?
【问题讨论】:
如果我们可以关闭一个旧问题,因为它不再是主题,那么我们可以重新打开一个旧问题,因为它关闭的原因不再有效。这是一个公平的问题,已经产生了很好的答案,所以投票重新开放。 【参考方案1】:集合基本上是一个散列,每个键/值对的值设置为相同的值。这是使它表现得像一个集合的关键。
一旦我们知道,保存和恢复 Set 就像保存 Array 或 Hash,并且可以通过多种方式完成。
@steenslag 提到使用Marshall.dump
,这很好。
因为 Set 是 Hash 的变体,所以也可以使用 YAML 或 JSON 来序列化数据。两者的最大优势是它们很容易在其他语言中重用。 YAML 和 JSON 通常用于在主机之间存储和传输数据,是可读性很强的格式。
这里有一些例子可以给你一些想法:
require 'set'
require 'json'
require 'yaml'
foo = Set.new
foo << 1
foo << 2
foo << 1
foo # => #<Set: 1, 2>
foo
是一个集合。也可以转换为数组:
foo.to_a # => [1, 2]
我们可以使用 YAML 来序列化 Set:
puts YAML.dump(foo)
# >> --- !ruby/object:Set
# >> hash:
# >> 1: true
# >> 2: true
而且,我们可以创建序列化版本,然后再次将其解析回 Set:
YAML.load(YAML.dump(foo)) # => #<Set: 1, 2>
因为foo
是一个Set,我们也可以把它转成一个Array,然后用YAML序列化:
puts YAML.dump(foo.to_a)
# >> ---
# >> - 1
# >> - 2
然后我们可以读回数据,如果我们选择,将其转换回 Set:
bar = YAML.load(YAML.dump(foo.to_a)).to_set
bar.class # => Set
bar # => #<Set: 1, 2>
或者,如果是读取 YAML 的语言,不支持 Set,如 Perl,则在 Perl 代码读取和解析数据时,可以将其保留为 Array。
JSON 的工作方式类似。以下是通过 Array 进行数据往返的示例:
foo.to_a.to_json # => "[1,2]"
JSON.parse(foo.to_a.to_json) # => [1, 2]
JSON.parse(foo.to_a.to_json).to_set # => #<Set: 1, 2>
JSON 还有[]
方法,它足够聪明,可以判断传入的参数是String 还是Array 或Hash。如果它是第一个参数,则解析并作为 Ruby 对象返回。如果是后两者,就序列化,变成字符串:
JSON[foo.to_a] # => "[1,2]"
JSON[JSON[foo.to_a]] # => [1, 2]
JSON[JSON[foo.to_a]].to_set # => #<Set: 1, 2>
在使用 JSON 或 YAML 的任何一种情况下,都可以使用几种不同的 IO 或 File 方法轻松地读取和写入结果字符串。查看File.write 和File.read,它们都继承自IO,如果您决定使用YAML,请查看YAML.load_file
, which is inherited from Psych。
【讨论】:
【参考方案2】:Marshal 模块以字符串形式转储对象,可以将其写入文件。读取文件并Marshal.load
'ing 字符串给出原始对象。
Marshal.dump
采用描述为“anIO”的可选参数;在实践中:一个文件。
h = "hi" => 1
# dumping:
File.open("test.marshal", "w")|to_file| Marshal.dump(h, to_file)
# retrieving:
p File.open("test.marshal", "r")|from_file| Marshal.load(from_file) #=> "hi"=>1
注意事项
Marshal.dump 创建的文件格式可以随着不同的 Ruby 版本或实现而改变。如果您需要创建一个任何版本的 Ruby 都可以读取的文件,那么最好使用 YAML 或 JSON 之类的文件,而不是 Marshal.dump。
有些对象不能序列化(也就是说,不能使用 Marhsal.dump 转储)。 Lambdas 和 procs 属于这些对象,因此如果您的哈希设置了其default_proc
属性,那么您将无法编组该哈希。要解决此问题,您可以在保存之前将 default_proc
设置为 nil(例如 my_hash.default_proc = nil
),但您需要在加载哈希后将 default_proc
重置为正确的值。
【讨论】:
以上是关于如何将任意 Ruby 对象保存到磁盘并在必要时将其读回? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Ruby 将数据保存到 JSON 中并在以后使用?
如何访问 Hololens 3D 对象文件夹中的文件并在运行时将其发送到应用程序
如何将 UIView 锚定到屏幕上的特定位置并在滚动时将其保留在那里