Ruby序列化和持久化存储(Marshal、Pstore)操作方法详解

Ruby Marshal序列化

Marshal是Ruby的核心库,可以将一些对象以二进制的方式序列化保存到文件中,需要时再从文件中加载重新构建成对象,即反序列化。

Marshal对数值、字符串、数组、布尔值等基础数据的序列化保存没有任何问题。

但并非所有类型的数据都能序列化。Marshal从序列化文件中加载并重新构建成对象的过程中会执行一些操作,但还原的过程有些内容可能会丢失它不能序列化I0流对象以及代码类对象: Proc对象、 单例对象、匿名类和模块,这是它的限制所在。

序列化和反序列化的过程非常简单:

# 一个嵌套数组
arr = [
  %w(Perl Python PHP),
  %w(C C++ Java Golang),
  %w(Shell Powershell Cmdline)
  ]

# 将arr对象序列化保存到文件中
File.open('/tmp/data.dat', "w") do |file|
  Marshal.dump(arr, file)
end

# 反序列化
File.open('/tmp/data.dat') do |file|
  data = Marshal.load(file)
end

p data

Marshal.dump()还可以通过第三个参数指定最多允许序列化多少个嵌套的对象层次,即深度,超出了深度将报错。其默认值为-1,此时表示不检查深度,即dump所有层次。例如:

arr = [
  %w(Perl Python PHP),
  [ %w(C C++), %(Java Golang) ],   #=> 3层
  %w(Shell Powershell Cmdline)
  ]

# 将arr对象序列化保存到文件中
File.open('/tmp/data.dat', "w") do |file|
  Marshal.dump(arr, file, 4)      #=> 小于4将报错
end

如果想要指定对象中要序列化的内容,或者指定序列化成什么类型,可以在类中编写marshal_dumpmarshal_load方法。例如,只dump一部分数据并以数组的方式保存:

class Klass
  def initialize name, age, height
    @name = name
    @age = age
    @height = height
  end

  def marshal_dump
    [@name, @age]
  end

  # 反序列化,arr是序列化时的数组
  # 最终它返回一个Klass的实例对象
  def marshal_load arr
    @name, @age = arr
  end
end

# 序列化Klass的一个对象,但只会包含name和age两个属性
obj = Klass.new("junmajinlong", 23, 170)
File.open('/tmp/me.dat','w') do |file|
  Marshal.dump(obj, file)
end

# 反序列化,得到一个Klass的实例对象,并设置name和age属性
obj1 = File.open("/tmp/me.dat") do |file|
  Marshal.load file
end

p obj1
#=> #<Klass:0x00007fffcc0119f8 @name="junmajinlong", @age=23>

显然,上面反序列化的过程中缺少了一个height属性。为了让对象完整,在反序列化的时候需要根据反序列化得到的结果合理构建新对象。例如,使用instance_eval()构建新对象:

def marshal_load arr
  self.instance_eval do
    initialize(*arr, 170)
  end
end

Ruby Pstore存储

Pstore(persistence store)是Ruby的一个持久化存储的标准库,它以基于Hash数据类型的方式将数据以key-value的方式存储在文件中(二进制的),其中value是想要存储的数据,key是这部分数据的一个名称。

在Pstore中,key称为root,每个key都是一个root。

Pstore是基于事务的,所以多次增删改数据的过程是原子的,可统一提交(commit)、统一回滚(abort)。commit()和abort()时都会立即终止本次事务,所以它们后面的代码不会执行,如果没有指定commit()或abort(),则在退出transaction的时候自动保存。

因为pstore每次读都要先加载文件部分内容到内存(直到找到对应的key),所以读效率不高。再者,每次写入都需要拷贝文件的绝大部分数据,所以效率更低。因此,Pstore只适用于少量数据、少量读写的数据存储场景。

例如,持久化保存到文件:

require 'pstore'

s = PStore.new('/tmp/pstore.dat')

s.transaction do
  s["p1"] = {name: "junmajinlong", age: 23, height: 170 }
  s["p2"] = {name: "junma", age: 22, height: 180}
  s.commit
  s["p3"] = {name: "jinlong", age: 24}
end

s.transaction do
  # 覆盖p2
  s["p2"] = {name: "jinlong", age: 24, height: 170 }
end   #=> 自动commit

从pstore文件中读取数据:

require 'pstore'

s = PStore.new("/tmp/pstore.dat")

p2 = s.transaction do
  s["p2"]
end
p p2
puts p2.name

transaction(read_only=false)还可以指定参数设置该事务是否只读,如果设置了只读,则事务内对pstore做任何修改都会抛出错误。

Pstore还有其它一些辅助方法:

[KEY]     :获取元素的值,如果元素不存在则返回nil
delete()  :删除元素,可指定元素不存在时的默认值参数
fetch()   :获取元素,如果元素不存在,默认报错,可指定默认返回值
path()    :返回pstore文件的路径
root?()   :检查key是否存在
roots()   :返回所有的key

更多关于Ruby序列化和持久化存储(Marshal、Pstore)操作方法请查看下面的相关链接

(0)

相关推荐

  • 在Ruby程序中连接数据库的详细教程

    本章节将向您讲解如何使用 Ruby 访问数据库.Ruby DBI 模块为 Ruby 脚本提供了类似于 Perl DBI 模块的独立于数据库的接口. DBI 即 Database independent interface,代表了 Ruby 独立于数据库的接口.DBI 在 Ruby 代码与底层数据库之间提供了一个抽象层,允许您简单地实现数据库切换.它定义了一系列方法.变量和规范,提供了一个独立于数据库的一致的数据库接口. DBI 可与下列进行交互: ADO (ActiveX Data Object

  • ruby+nokogori抓取糗事百科前10页并存储进数据库示例

    ruby,nokogori,爬取糗事百科最新的10页加图片比并同时保存进文本跟数据库 复制代码 代码如下: #encoding:utf-8require "open-uri"require "nokogiri"require "mysql"@dbh=Mysql.real_connect("localhost","root","dengli","pachong")@fi

  • 浅谈Ruby on Rails下的rake与数据库数据迁移操作

    不知道你有没有把数据迁移写入Migration文件的经历,相信无论是老鸟还是新手都这样干过吧.事实上,这样做并不是行不通,只不过这样的实践慢慢会给你引入一些不必要的麻烦. 一般认为db/migrate文件夹里的内容是关于你数据库Schema的演变过程,每个新的开发或线上环境都要通过这些Migration来构建可用的数据库.但如果这里装入了,负责细节的业务代码,比如一些历史遗留数据的迁移代码之类的,当一段时间后,数据库的结构变化了,但Migration没有跟着变化,渐渐的曾经的辅助代码,就成了垃圾

  • Ruby连接使用windows下sql server数据库代码实例

    require 'win32ole' class SqlServer # This class manages database connection and queries attr_accessor :connection, :data, :fields def initialize @connection = nil @data = nil end def open # Open ADO connection to the SQL Server database connection_st

  • Ruby中访问SQL Server数据库的配置实例

    因为工作需要,要分析存放在SQL Server上的数据,所以不得不研究一下如何使用Ruby访问SQL Server,发现其实还是很简单的: 安装FreeTDS 下载FreeTDS源代码 解压编译安装: 复制代码 代码如下: ./configure --prefix=/usr/local/freetds && make && sudo make install 安装Tiny_TDS Tiny_TDS,安装和使用非常简单,推荐使用: 复制代码 代码如下: sudo gem in

  • Ruby序列化和持久化存储(Marshal、Pstore)操作方法详解

    Ruby Marshal序列化 Marshal是Ruby的核心库,可以将一些对象以二进制的方式序列化保存到文件中,需要时再从文件中加载重新构建成对象,即反序列化. Marshal对数值.字符串.数组.布尔值等基础数据的序列化保存没有任何问题. 但并非所有类型的数据都能序列化.Marshal从序列化文件中加载并重新构建成对象的过程中会执行一些操作,但还原的过程有些内容可能会丢失它不能序列化I0流对象以及代码类对象: Proc对象. 单例对象.匿名类和模块,这是它的限制所在. 序列化和反序列化的过程

  • Go语言学习之文件操作方法详解

    目录 引言 1. 打开和关闭文件 2. 读取文件 2.1 defer 语句 2.2 手动宕机处理 2.3 打开文件并获取内容 2.4 bufio 读取文件 2.5 ioutil 读取文件 2.6 读取奇偶行内容 3. 写入文件 3.1 os.OpenFile() 函数 3.2 Write 和 WriteString 方式写入 3.3 bufio.NewWriter 方式写入 3.4 ioutil.WriteFile 方式写入 引言 计算机的文件是存储再外部介质(硬盘)上的数据集合,文件分为文本文

  • Flutter的键值存储数据库使用示例详解

    目录 Flutter 键值存储数据库 unqlite unqlite_flutter 快速上手 简单键值对存储 JSON 为什么你应该使用unqlite_flutter? Flutter 键值存储数据库 键值存储是开发中十分常见的需求,在Flutter开发中,一般使用 shared_preferences 插件来实现.shared_preferences 本质上就是将键值对保存到一个XML文件中进行持久化. 而shared_preferences 实际上存在一定缺陷,譬如其性能较差,不适合处理大

  • Docker容器操作方法详解

    目录 一.常用命令 1.创建并启动容器 2.列出所有容器 3.进入容器 4.退出容器 5.停止容器 6.启动/重启一个已停止的容器 7.删除容器 二.使用帮助 一.常用命令 下面按照使用容器中的流程: 创建并启动容器 > 查询容器 > 进入容器 > 退出容器 > 停止容器 > 启动/重启容器 > 删除容器来介绍Dockers常用命令,带领小伙伴快速入门. 1.创建并启动容器 docer run 当操作者执行docker run时,运行的容器进程是隔离的,因为它有自己的文

  • jQuery中each()、find()和filter()等节点操作方法详解(推荐)

    1.each(callback) 官方解释: 返回值:jQuery 概述 以每一个匹配的元素作为上下文来执行一个函数. 意味着,每次执行传递进来的函数时,函数中的this关键字都指向一个不同的DOM元素(每次都是一个不同的匹配元素).而且,在每次执行函数时,都会给函数传递一个表示作为执行环境的元素在匹配的元素集合中所处位置的数字值作为参数(从零开始的整型). 返回 'false' 将停止循环 (就像在普通的循环中使用 'break').返回 'true' 跳至下一个循环(就像在普通的循环中使用'

  • Python之str操作方法(详解)

    1. str.format():使用"{}"占位符格式化字符串(占位符中的索引号形式和键值对形式可以混合使用). >>> string = 'python{}, django{}, tornado{}'.format(2.7, 'web', 'tornado') # 有多少个{}占位符就有多少个值与其对应,按照顺序"填"进字符串中 >>> string 'python2.7, djangoweb, tornadotornado'

  • django基础之数据库操作方法(详解)

    Django 自称是"最适合开发有限期的完美WEB框架".本文参考<Django web开发指南>,快速搭建一个blog 出来,在中间涉及诸多知识点,这里不会详细说明,如果你是第一次接触Django ,本文会让你在感性上对Django有个认识,完成本文操作后会让你有兴趣阅读的相关书籍和文档. 本文客操作的环境,如无特别说明,后续都以下面的环境为基础: =================== Windows 7/10 python 3.5 Django 1.10 ======

  • Python之re操作方法(详解)

    一:re.search():search返回的是查找结果的对象,可以使用group()或groups()方法得到匹配成功的字符串. ①group() 默认返回匹配成功的整个字符串(忽略pattern中的括号),也可以指定返回匹配成功的括号中第几个字符串(从1开始计数): ②groups() 以元组的形式返回匹配成功的pattern中括号中的内容,若pattern中没有括号,则返回空元组. 以上这篇Python之re操作方法(详解)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多

  • Python之os操作方法(详解)

    1. os.path.driname(path):返回路径的上一级路径字符串. >>> os.path.dirname('D:\Games') 'D:\\' >>> 2. os.path.basename(path):返回路径的最后一级目录名(文件夹名)或文件名(全称). >>> os.path.basename('D:\Games\9yin_632\蜗牛整包\\0x0804.ini') '0x0804.ini' >>> 3. os.

  • java序列化与ObjectOutputStream和ObjectInputStream的实例详解

    java序列化与ObjectOutputStream和ObjectInputStream的实例详解 一个测试的实体类: public class Param implements Serializable { private static final long serialVersionUID = 5187074869820982336L; private Integer param1; private String param2; public Integer getParam1() { re

随机推荐