- 浏览: 1399894 次
- 性别:
- 来自: 火星
文章分类
最新评论
-
aidd:
内核处理time_wait状态详解 -
ahtest:
赞一下~~
一个简单的ruby Metaprogram的例子 -
itiProCareer:
简直胡说八道,误人子弟啊。。。。谁告诉你 Ruby 1.9 ...
ruby中的类变量与类实例变量 -
dear531:
还得补充一句,惊群了之后,数据打印显示,只有一个子线程继续接受 ...
linux已经不存在惊群现象 -
dear531:
我用select试验了,用的ubuntu12.10,内核3.5 ...
linux已经不存在惊群现象
经常我们需要以一种更透明的方式来存储和得到数据.Marshal模块提供了简单的对象持久化,PStore 库建立在这项技术之上。dbm 库使用像hash一样并永久的存贮在磁盘上.
1简单的Marshaling
经常我们需要创建一个对象,然后为了以后的使用保存它.ruby对这种对象持久化(或者说是Marshaling)提供了基本的支持.Marshal 模块能够使程序员序列化和反序列化一个ruby对象.
这里要注意的是这种技术并不是所有的对象能被dump.如果一个对象包含一个低级别的类的对象,他就不能被dump,比如IO、Proc和Binding,单例对象,匿名对象,模块也不能被序列化.
Marshal.dump 还有另外两种参数的形式,如果调用时传入一个参数的话,它将会返回返回一个由字符串表示的数据,其中前两个字节为主版本号和次版本号:
这边的话1.9和1.8的结果是不同的:
上面的结果是1.8打印出的结果,而1.9中,结果将会是\004和\b,也就是说它已经没有版本号了.
经常你如果想载入这些数据,当且仅当主版本号相同,次版本号相等或者小于时才会load。如果ruby解释器使用了verbose 参数的话,则版本号必须完全匹配.
第三个参数limit 只有当被序列化的对象是一个嵌套对象时才有意义,它就是遍历时的深度,当你的对象的嵌套深度大于等于你的limit时,就会抛出ArgumentError:
第三个参数的默认值是1,-1的话就是不进行深度检测.
2 更复杂的Marshaling
有时候由于一些限制,我们需要定制我们的序列化。通过创建_load和 _dump 方法我们可以做到定制.这两个方法是当序列化完成时调用的.
接下来的例子中,这个人从出生就赚取5%的利息在他的初始帐户中。 我们这里没有保存年龄和当前的余额,这是因为他们都是时间的函数:
当保存对象时不会计算年龄和当前余额,对象再生的时候,年龄和当前余额会被计算.注意marshal_load 会假设已经存在一个对象,这时就调用initialize就可以了。
3 使用Marshal执行受限制的深度拷贝.
ruby没有深度拷贝的操作,方法dup和clone可能不会是你所想象的那样.一个对象可能包含一个嵌套的对象引用,这时执行一个copy操作,就好像Pick-Up-Sticks的游戏一样.
我们这里提供了一个受限制的深度拷贝,受限制是因为它使用Marshal ,而Marshal是有很多局限的:
4 使用PStore进行更好的持久化
PStore 库提供给我们基于文件的ruby对象的持久化存储,一个PStore对象能够持有一个ruby对象的一些层次,每一个层次都有一个通过一个key来标识的root.当一个事务开始时从一个磁盘文件读取层次,当事务结束时将其回写:
通常我们能够直接传入PStore 对象给一个事务代码块。
在事务的进行中间我们能够通过commit或者abort方法进行终止.前者保持我们做的改变,后者则是放弃改变:
在事务中,你也可以使用方法roots 来返回一个根的数组,也有一个delete方法来删除一个root:
5 处理CSV数据
这边我们主要介绍FasterCSV库,因为它比起ruby内置的csv库更快.
CSV模块(csv.rb)能够按照csv的格式生成或者解析数据,对于csv的格式并没有一个统一的观点.FasterCSV库的作者定义了自己的csv的格式的标准:
让我们以创建一个文件开始,为了写一个逗号分割的数据,我们可以简单的以写模式打开文件:
上面的代码生成一个data.csv文件。
下面的程序负责读取:
更高级的特性可以去ruby-doc.org去看.
6 用YAML进行序列化
YAML 的意思是YAML Ain't Markup Language.他就是一种灵活的适合人阅读的一种存储格式。它和xml很类似,可是更优美.
当我们require yaml后,每个对象都将会有一个to_yaml 方法:
to_yaml 方法刚好和YAML.load 方法相反,我么能给他一个字符串或者一个流为参数.
假设我们有一个data.yaml 的文件:
如果我们现在load这个流,我们将会得到刚才的数组:
7 使用Madeleine进行对象的Prevalence
在一些领域,对象的Prevalence很流行,主要的观点是,内存很便宜并且越来越便宜, 而数据库却很小,因此忘掉数据库,保持所有的对象在内存里.
java实现的版本叫做Prevayler,而相应于ruby的版本叫做Madeleine.
Madeleine并不是对每一个人或者每一个程序都适用的.对象的prevalence有它自己的规则和限制。首先所有对象都必须得全部装载到内存里,其次所有的对象都必须能够被序列化(marshalable).
所有的对象都必须是确定的,也就是说有点像数学中的函数,输入相同,输出也一定相同(这意味着使用system clock或者随机数是不可以的).
对象应当尽可能地和所有的IO相隔离,也就是说一般要在prevalence 系统外调用这些IO操作.
最后,每一个改变prevalence 系统的命令都必须像一个命令对象的形式发出.
想研究Madeleine的,只能自己找资料了.
8 使用DBM 库
dbm是一个平台相关的,基于字符串的散列文件存储 机制。它存储一个key和一个和这个key联系在一起的数据,他们都是字符串.
可以看例子:
DBM类mix了Enumerable模块,他的类方法new和open都是singletons:
操作dbm对象和操作hash对象差不多,想了解它的具体的方法可以去看文档.
1简单的Marshaling
经常我们需要创建一个对象,然后为了以后的使用保存它.ruby对这种对象持久化(或者说是Marshaling)提供了基本的支持.Marshal 模块能够使程序员序列化和反序列化一个ruby对象.
# array of elements [composer, work, minutes] works = [["Leonard Bernstein","Overture to Candide",11], ["Aaron Copland","Symphony No. 3",45], ["Jean Sibelius","Finlandia",20]] # We want to keep this for later... File.open("store","w") do |file| Marshal.dump(works,file) end # Much later... File.open("store") do |file| works = Marshal.load(file) end
这里要注意的是这种技术并不是所有的对象能被dump.如果一个对象包含一个低级别的类的对象,他就不能被dump,比如IO、Proc和Binding,单例对象,匿名对象,模块也不能被序列化.
Marshal.dump 还有另外两种参数的形式,如果调用时传入一个参数的话,它将会返回返回一个由字符串表示的数据,其中前两个字节为主版本号和次版本号:
这边的话1.9和1.8的结果是不同的:
s = Marshal.dump(works) p s[0] # 4 p s[1] # 8
上面的结果是1.8打印出的结果,而1.9中,结果将会是\004和\b,也就是说它已经没有版本号了.
经常你如果想载入这些数据,当且仅当主版本号相同,次版本号相等或者小于时才会load。如果ruby解释器使用了verbose 参数的话,则版本号必须完全匹配.
第三个参数limit 只有当被序列化的对象是一个嵌套对象时才有意义,它就是遍历时的深度,当你的对象的嵌套深度大于等于你的limit时,就会抛出ArgumentError:
File.open("store","w") do |file| arr = [ ] Marshal.dump(arr,file,0) # in `dump': exceed depth limit # (ArgumentError) Marshal.dump(arr,file,1) arr = [1, 2, 3] Marshal.dump(arr,file,1) # in `dump': exceed depth limit # (ArgumentError) Marshal.dump(arr,file,2) arr = [1, [2], 3] Marshal.dump(arr,file,2) # in `dump': exceed depth limit # (ArgumentError) Marshal.dump(arr,file,3) end File.open("store") do |file| p Marshal.load(file) # [ ] p Marshal.load(file) # [1, 2, 3] p Marshal.load(file) # arr = [1, [2], 3] end
第三个参数的默认值是1,-1的话就是不进行深度检测.
2 更复杂的Marshaling
有时候由于一些限制,我们需要定制我们的序列化。通过创建_load和 _dump 方法我们可以做到定制.这两个方法是当序列化完成时调用的.
接下来的例子中,这个人从出生就赚取5%的利息在他的初始帐户中。 我们这里没有保存年龄和当前的余额,这是因为他们都是时间的函数:
class Person attr_reader :name attr_reader :age attr_reader :balance def initialize(name,birthdate,beginning) @name = name @birthdate = birthdate @beginning = beginning @age = (Time.now - @birthdate)/(365*86400) @balance = @beginning*(1.05**@age) end def marshal_dump Struct.new("Human",:name,:birthdate,:beginning) str = Struct::Human.new(@name,@birthdate,@beginning) str end def marshal_load(str) self.instance_eval do initialize(str.name, str.birthdate, str.beginning) end end # Other methods... end p1 = Person.new("Rudy",Time.now - (14 * 365 * 86400), 100) p [p1.name, p1.age, p1.balance] # ["Rudy", 14.0, 197.99315994394] str = Marshal.dump(p1) p2 = Marshal.load(str) p [p2.name, p2.age, p2.balance] # ["Rudy", 14.0, 197.99315994394]
当保存对象时不会计算年龄和当前余额,对象再生的时候,年龄和当前余额会被计算.注意marshal_load 会假设已经存在一个对象,这时就调用initialize就可以了。
3 使用Marshal执行受限制的深度拷贝.
ruby没有深度拷贝的操作,方法dup和clone可能不会是你所想象的那样.一个对象可能包含一个嵌套的对象引用,这时执行一个copy操作,就好像Pick-Up-Sticks的游戏一样.
我们这里提供了一个受限制的深度拷贝,受限制是因为它使用Marshal ,而Marshal是有很多局限的:
def deep_copy(obj) Marshal.load(Marshal.dump(obj)) end a = deep_copy(b)
4 使用PStore进行更好的持久化
PStore 库提供给我们基于文件的ruby对象的持久化存储,一个PStore对象能够持有一个ruby对象的一些层次,每一个层次都有一个通过一个key来标识的root.当一个事务开始时从一个磁盘文件读取层次,当事务结束时将其回写:
require "pstore" # save db = PStore.new("employee.dat") db.transaction do db["params"] = {"name" => "Fred", "age" => 32, "salary" => 48000 } end # retrieve require "pstore" db = PStore.new("employee.dat") emp = nil db.transaction { emp = db["params"] }
通常我们能够直接传入PStore 对象给一个事务代码块。
在事务的进行中间我们能够通过commit或者abort方法进行终止.前者保持我们做的改变,后者则是放弃改变:
require "pstore" # Assume existing file with two objects stored store = PStore.new("objects") store.transaction do |s| a = s["my_array"] h = s["my_hash"] # Imaginary code omitted, manipulating # a, h, etc. # Assume a variable named "condition" having # the value 1, 2, or 3... case condition when 1 puts "Oops... aborting." s.abort # Changes will be lost. when 2 puts "Committing and jumping out." s.commit # Changes will be saved. when 3 # Do nothing... end puts "We finished the transaction to the end." # Changes will be saved. end
在事务中,你也可以使用方法roots 来返回一个根的数组,也有一个delete方法来删除一个root:
store.transaction do |s| list = s.roots # ["my_array","my_hash"] if s.root?("my_tree") puts "Found my_tree." else puts "Didn't find # my_tree." end s.delete("my_hash") list2 = s.roots # ["my_array"] end
5 处理CSV数据
这边我们主要介绍FasterCSV库,因为它比起ruby内置的csv库更快.
CSV模块(csv.rb)能够按照csv的格式生成或者解析数据,对于csv的格式并没有一个统一的观点.FasterCSV库的作者定义了自己的csv的格式的标准:
引用
Record separator: CR + LF
Field separator: comma (,)
Quote data with double quotes if it contains CR, LF, or comma
Quote double quote by prefixing it with another double quote ("-> "")
Empty field with quotes means null string (data,"",data)
Empty field without quotes means NULL (data,,data)
Field separator: comma (,)
Quote data with double quotes if it contains CR, LF, or comma
Quote double quote by prefixing it with another double quote ("-> "")
Empty field with quotes means null string (data,"",data)
Empty field without quotes means NULL (data,,data)
让我们以创建一个文件开始,为了写一个逗号分割的数据,我们可以简单的以写模式打开文件:
require 'csv' CSV.open("data.csv","w") do |wr| wr << ["name", "age", "salary"] wr << ["mark", "29", "34500"] wr << ["joe", "42", "32000"] wr << ["fred", "22", "22000"] wr << ["jake", "25", "24000"] wr << ["don", "32", "52000"] end
上面的代码生成一个data.csv文件。
引用
"name","age","salary"
"mark",29,34500
"joe",42,32000
"fred",22,22000
"jake",25,24000
"don",32,52000
"mark",29,34500
"joe",42,32000
"fred",22,22000
"jake",25,24000
"don",32,52000
下面的程序负责读取:
require 'csv' CSV.open('data.csv', 'r') do |row| p row end # Output: # ["name", "age", "salary"] # ["mark", "29", "34500"] # ["joe", "42", "32000"] # ["fred", "22", "22000"] # ["jake", "25", "24000"] # ["don", "32", "52000"]
更高级的特性可以去ruby-doc.org去看.
6 用YAML进行序列化
YAML 的意思是YAML Ain't Markup Language.他就是一种灵活的适合人阅读的一种存储格式。它和xml很类似,可是更优美.
当我们require yaml后,每个对象都将会有一个to_yaml 方法:
require 'yaml' str = "Hello, world" num = 237 arr = %w[ Jan Feb Mar Apr ] hsh = {"This" => "is", "just a"=>"hash."} puts str.to_yaml puts num.to_yaml puts arr.to_yaml puts hsh.to_yaml # Output: # --- "Hello, world" # --- 237 # --- # - Jan # - Feb # - Mar # - Apr # --- # just a: hash. # This: is
to_yaml 方法刚好和YAML.load 方法相反,我么能给他一个字符串或者一个流为参数.
假设我们有一个data.yaml 的文件:
引用
---
- "Hello, world"
- 237
-
- Jan
- Feb
- Mar
- Apr
-
just a: hash.
This: is
- "Hello, world"
- 237
-
- Jan
- Feb
- Mar
- Apr
-
just a: hash.
This: is
如果我们现在load这个流,我们将会得到刚才的数组:
require 'yaml' file = File.new("data.yaml") array = YAML.load(file) file.close p array # Output: # ["Hello, world", 237, ["Jan", "Feb", "Mar", "Apr"], # {"just a"=>"hash.", "This"=>"is"}]
7 使用Madeleine进行对象的Prevalence
在一些领域,对象的Prevalence很流行,主要的观点是,内存很便宜并且越来越便宜, 而数据库却很小,因此忘掉数据库,保持所有的对象在内存里.
java实现的版本叫做Prevayler,而相应于ruby的版本叫做Madeleine.
Madeleine并不是对每一个人或者每一个程序都适用的.对象的prevalence有它自己的规则和限制。首先所有对象都必须得全部装载到内存里,其次所有的对象都必须能够被序列化(marshalable).
所有的对象都必须是确定的,也就是说有点像数学中的函数,输入相同,输出也一定相同(这意味着使用system clock或者随机数是不可以的).
对象应当尽可能地和所有的IO相隔离,也就是说一般要在prevalence 系统外调用这些IO操作.
最后,每一个改变prevalence 系统的命令都必须像一个命令对象的形式发出.
想研究Madeleine的,只能自己找资料了.
8 使用DBM 库
dbm是一个平台相关的,基于字符串的散列文件存储 机制。它存储一个key和一个和这个key联系在一起的数据,他们都是字符串.
可以看例子:
require 'dbm' d = DBM.new("data") d["123"] = "toodle-oo!" puts d["123"] # "toodle-oo!" d.close puts d["123"] # RuntimeError: closed DBM file e = DBM.open("data") e["123"] # "toodle-oo!" w=e.to_hash # {"123"=>"toodle-oo!"} e.close e["123"] # RuntimeError: closed DBM file w["123"] # "toodle-oo!
DBM类mix了Enumerable模块,他的类方法new和open都是singletons:
q=DBM.new("data.dbm") # f=DBM.open("data.dbm") # Errno::EWOULDBLOCK: # Try again - "data.dbm"
操作dbm对象和操作hash对象差不多,想了解它的具体的方法可以去看文档.
发表评论
-
一个创建闭包的小技巧
2008-06-05 00:12 2131一个小技巧,在Ola Bini 的blog上看到的。 假设你 ... -
解决Colored Cubes问题
2008-06-02 10:43 2785Engineering Puzzle You have fo ... -
ruby1.9中的Iterators
2008-03-05 22:37 3719在ruby1.9中增加了External Iterators这 ... -
一个简单的ruby Metaprogram的例子
2008-03-03 23:49 4102比如下面一个文件 people.txt 引用name,age ... -
Ruby Object Model
2008-03-03 19:29 3574刚好看到,保存一下. -
一个检测方法的参数类型的小程序
2008-03-02 22:48 3248今天没事看blog的时候,看到一个小子实现了这个,不过他的程序 ... -
rails中的BlankSlate源码分析
2008-02-28 23:27 3446其实这个类实现的功能很简单,那就是实现一个没有predefin ... -
ruby中的类变量与类实例变量
2008-02-26 21:15 7634首先,在ruby1.8中类变量是所有子类和父类共享的,可以看下 ... -
在ubuntu上共存多个版本的ruby
2008-02-24 15:20 4376今天装Revactor库的时候,真把我郁闷了,没想到ubunt ... -
看到了一个用ruby写的scheme解释器
2008-02-16 21:35 3769,自己本来想等啥时候有时间做个类似的东西呢,没想到已经有人做 ... -
ruby way之处理RSS和Atom
2008-01-31 01:32 35191 rss 标准库 RSS 是基于xml的,因此你能简单的将 ... -
ruby way之使用REXML解析xml
2008-01-30 00:35 9253REXML 是一个完全用ruby写的processor ,他有 ... -
rails2中的一些被废弃的用法
2008-01-29 00:33 2542这些只是自己最近看web开发敏捷之道的时候(由于书中的版本是1 ... -
ruby way之动态特性之二
2008-01-25 00:49 36791 得到所定义的实体的列表 ruby的反射api能够使我们在 ... -
ruby way之动态特性之一
2008-01-23 01:25 45401 动态的evaluate代码 全局的方法eval 编译并且 ... -
ruby way之高级OOP特性之二
2008-01-20 03:43 29491 把代码像对象一样存储 当你想要以对象的形式存储一块代码的 ... -
ruby way之高级OOP特性之一
2008-01-19 12:14 22631 发送一条消息给一个对象 当你调用一个方法时,你也就是发送 ... -
ruby way之OOP之二
2008-01-16 23:59 23631 理解allocate 在一些特殊的环境中,你可能需要不调 ... -
ruby way之OOP之一
2008-01-16 00:25 26311 使用多个构造方法 在ruby中没有像c++或者ruby中 ... -
ruby way之连接数据库
2008-01-14 00:47 2475这边都只是个大概,具体的要自己去看文档了. 1 连接SQLi ...
相关推荐
The Ruby Way 第三版(英文版),全书22章,书中包含600多个按主题分类的示例。每个示例都回答了“如何使用Ruby来完成”的问题。 ——Ruby on Rails之父David Heinemeier Hansson倾力推荐!
The Ruby Way(第2版) <br>The Ruby Way assumes that the reader is already familiar with the subject matter. Using many code samples it focuses on "how-to use Ruby" for specific applications, either ...
《The Ruby Way 2nd Edition》是一本深入探讨Ruby编程语言的经典著作,旨在帮助读者全面理解和掌握Ruby的精髓。这本书的第二版在2006年出版,由Addison-Wesley出版,作者通过深入浅出的方式,揭示了Ruby语言的强大...
《The Ruby Way 第二版》...“《The Ruby Way (第2版)中文版》在阐述元编程(metaprogramming)等方面尤其出类拔萃,而元编程是Ruby最引人注目的方面之一。” ——Ruby on Rails之父David Heinemeier Hansson倾力推荐!
the ruby way the ruby way
内含以下4个文档: 1、Addison.Wesley.The.Ruby.Way.2nd.Edition.Oct.2006.chm 2、O'Reilly.Learning.Ruby.May.2007.chm 3、Programming Ruby 2e.pdf 4、ruby中文文档.chm
Ruby-chewy是一个高级的Elasticsearch Ruby框架,它构建在官方的elasticsearch-ruby客户端之上,为开发者提供了更简洁、强大的接口来操作Elasticsearch。这篇文章将深入探讨chewy框架的核心特性、如何安装与配置,...
通过阅读《The Ruby Way》,你不仅能学会Ruby的基础,还能掌握高级特性和最佳实践。书中的实例代码和解决问题的思路将帮助你成为一名更高效的Ruby开发者。同时,这本书也适合已经有一定编程经验的人用来提升对Ruby...
5. **高级数据结构操作**:除了基本的数据类型外,还涉及到了哈希表、数组以及其他数据结构如栈、树和图的操作。 6. **输入/输出与文件处理**:介绍了如何处理一般的输入/输出操作、文件操作以及持久化对象。 7. *...
总之,《Ruby Way》是了解和学习Ruby语言的重要资源,它涵盖了Ruby的基本概念、核心语法、高级特性以及实际应用,对于想要进入Ruby世界的开发者来说,是一本不可多得的指南。通过深入阅读和实践书中的例子,你将能够...
R和Ruby数据分析之旅 数据分析 数据挖掘
在Ruby编程语言中,时间日期处理是至关重要的,特别是在开发涉及日志记录、事件调度或数据分析的应用程序时。"11.5 时间日期the ruby way"这个主题深入探讨了Ruby中处理时间日期的最佳实践和常见用法。让我们逐一...
如果你对万事万物的运行方式充满好奇,这本有趣的《R和Ruby数据分析之旅》会帮你找到日常生活中某些问题的真正答案。借助基本的数学方法,并使用Ruby和R语言做一些简单的编程工作,你就能学会如何对问题建模,并找出...
除了基础的文件和目录操作外,Ruby还支持更高级的数据存储技术,例如对象序列化、持久化存储库等。 **对象序列化**: `Marshal`模块提供了简单对象序列化的能力,可以将对象转换为二进制格式并保存到文件中。 ```...
Ruby是一种强大的动态编程语言,尤其在数据处理方面表现出色。Map、Reduce和Select是Ruby中用于操作和处理数据的关键概念,它们在数据科学、分析和软件工程领域中扮演着重要角色。 1. **Ruby Map**: Map函数允许...