如何将对象保存到文件中?

Posted

技术标签:

【中文标题】如何将对象保存到文件中?【英文标题】:How can I save an object to a file? 【发布时间】:2011-05-17 15:35:15 【问题描述】:

我想将一个对象保存到一个文件中,然后轻松地从文件中读取它。作为一个简单的例子,假设我有以下 3d 数组:

m = [[[0, 0, 0],
 [0, 0, 0],
 [0, 0, 0]],
[[0, 0, 0],
 [0, 0, 0],
 [0, 0, 0]]]

是否有一个简单的 Ruby API 可以用来实现此目的,而无需编写解析器来解释文件中的数据?在我给出的示例中,这很简单,但是随着对象变得越来越复杂,使对象持久化变得很烦人。

【问题讨论】:

【参考方案1】:

您需要先序列化对象,然后才能将它们保存到文件并反序列化它们以取回它们。正如 Cory 所说,有 2 个标准序列化库被广泛使用,MarshalYAML

MarshalYAML 分别使用 dumpload 方法进行序列化和反序列化。

以下是您可以如何使用它们:

m = [
     [
      [0, 0, 0],
      [0, 0, 0],
      [0, 0, 0]
     ],
     [
      [0, 0, 0],
      [0, 0, 0],
      [0, 0, 0]
     ]
    ]

# Quick way of opening the file, writing it and closing it
File.open('/path/to/yaml.dump', 'w')  |f| f.write(YAML.dump(m)) 
File.open('/path/to/marshal.dump', 'wb')  |f| f.write(Marshal.dump(m)) 

# Now to read from file and de-serialize it:
YAML.load(File.read('/path/to/yaml.dump'))
Marshal.load(File.read('/path/to/marshal.dump'))

您需要注意文件大小和与文件读取/写入相关的其他怪癖。

更多信息,当然可以在 API 文档中找到。

【讨论】:

没有足够的权限来编辑您的答案并将其添加到其中。 :-) @Swanand 实际上在 Ruby 2.0.0 中对我来说这是行不通的,而应该是 File.open('/path/to/file.extension', 'wb') |f| f.write(Marsshal.dump(m)) File.open('/path/to/file.extension', 'rb') |f| m = Marshal::load(f) (使其成为二进制读写,这在当时可能是标准的,否则弹出 ASCI-8BIT to UTF8-Conversion 错误) - 如果 m 是手动定义类的对象,我必须确保在 Marshall::load 工作之前加载这个类(否则你会得到类/模块未知错误) @YoLudke - 我认为Marshal#load 之前的类/模块加载是给定的,但您明确提及它是正确的。此外,此代码是用 1.8.7 编写的(也适用于 1.9.3),但感谢您指出 2.0.0。我会试一试并更新答案。 Marshal 不是一个很好的持久化工具,格式取决于 Ruby 版本,并且无法在新的 Ruby 中解码旧的 Marshal 格式。 "In normal use, marshaling can only load data written with the same major version number and an equal or lower minor version number.". @muistooshort 同意。【参考方案2】:

见元帅:http://ruby-doc.org/core/classes/Marshal.html

-或-

YAML:http://www.ruby-doc.org/core/classes/YAML.html

【讨论】:

Marshal 不是一个很好的持久化工具,格式取决于 Ruby 版本,并且无法在新的 Ruby 中解码旧的 Marshal 格式。 "In normal use, marshaling can only load data written with the same major version number and an equal or lower minor version number.".【参考方案3】:

YAML 和 Marshal 是最明显的答案,但根据您打算如何处理数据,sqlite3 也可能是一个有用的选项。

require 'sqlite3'

m = [[[0, 0, 0],
 [0, 0, 0],
 [0, 0, 0]],
[[0, 0, 0],
 [0, 0, 0],
 [0, 0, 0]]]

db=SQLite3::Database.new("demo.out")
db.execute("create table data (x,y,z,value)")
inserter=db.prepare("insert into data (x,y,z,value) values (?,?,?,?)")
m.each_with_index do |twod,z|
  twod.each_with_index do |row,y|
    row.each_with_index do |val,x|
      inserter.execute(x,y,z,val)
    end
  end
end

【讨论】:

我不推荐,sqlite3 有很多数据类型不一致,因为它从数据推断类型而不是使用严格的类型系统:sqlite.org/datatype3.html

以上是关于如何将对象保存到文件中?的主要内容,如果未能解决你的问题,请参考以下文章

如何将带有 NSValue 对象的 NSDictionary 保存到文件中

matlab如何将对象保存到文件中?

如何通过 JFileChooser 将 Icon 对象保存到文件中?

Javascript:如何将带有私有字段的对象保存到文件中?

如何使用 boto3 将 S3 对象保存到文件中

如何使用 LocalStorage 将 json 对象保存到 Assets 文件夹