Ruby 实用库功能解析与应用示例
在 Ruby 编程中,有许多实用的库可以帮助开发者实现各种功能,如邮件处理、网络连接、字符编码转换等。以下将详细介绍一些常用库的功能和使用方法。
1. Net::POP:访问 POP 邮件服务器
Net::POP 库提供了一个简单的客户端,用于在邮局协议(POP)服务器上获取和删除邮件。
Net::POP3
类用于访问 POP 服务器,返回一个
Net::POPMail
对象列表,每个对象代表服务器上存储的一条消息。
示例代码
require 'net/pop'
pop = Net::POP3.new('server.ruby-stuff.com')
pop.start('joe', 'secret') do |server|
msg = server.mails[0]
# Print the 'From:' header line
from = msg.header.split("\r\n").grep(/^From: /)[0]
puts from
puts
puts "Full message:"
text = msg.pop
puts text
end
输出结果
From: dave@facet.ruby-stuff.com (Dave Thomas)
Full message:
Return-Path: <dave@facet.ruby-stuff.com>
Received: from facet.ruby-stuff.com (facet.ruby-stuff.com [10.96.0.122])
by pragprog.com (8.11.6/8.11.6) with ESMTP id i2PJMW701809
for <joe@carat.ruby-stuff.com>; Thu, 25 Mar 2004 13:22:32 -0600
Received: by facet.ruby-stuff.com (Postfix, from userid 502)
id 4AF228B1BD; Thu, 25 Mar 2004 13:22:36 -0600 (CST)
To: joe@carat.ruby-stuff.com
Subject: Try out the new features!
Message-Id: <20040325192236.4AF228B1BD@facet.ruby-stuff.com>
Date: Thu, 25 Mar 2004 13:22:36 -0600 (CST)
From: dave@facet.ruby-stuff.com (Dave Thomas)
Status: RO
Ruby 1.8 has a boatload of new features, both in
the core language and in the supplied libraries.
Try it out!
2. Net::SMTP:简单 SMTP 客户端
Net::SMTP 库提供了一个简单的客户端,用于使用简单邮件传输协议(SMTP)发送电子邮件。它不协助创建消息负载,只是在构造好 RFC822 消息后发送消息。
2.1 从字符串发送电子邮件
require 'net/smtp'
msg = "Subject: Test\n\nNow is the time\n"
Net::SMTP.start('pragprog.com') do |smtp|
smtp.send_message(msg, 'dave@pragprog.com', ['dave'])
end
2.2 使用 SMTP 对象和适配器发送电子邮件
require 'net/smtp'
Net::SMTP::start('pragprog.com', 25, "pragprog.com") do |smtp|
smtp.open_message_stream('dave@pragprog.com', # from
[ 'dave' ] # to
) do |stream|
stream.puts "Subject: Test1"
stream.puts
stream.puts "And so is this"
end
end
2.3 向需要 CRAM - MD5 认证的服务器发送电子邮件
require 'net/smtp'
msg = "Subject: Test\n\nNow is the time\n"
Net::SMTP.start('pragprog.com', 25, 'pragprog.com',
'user', 'password', :cram_md5) do |smtp|
smtp.send_message(msg, 'dave@pragprog.com', ['dave'])
end
3. Net::Telnet:Telnet 客户端
Net::Telnet 库提供了一个完整的 Telnet 客户端实现,并包含一些功能,使其成为与非 Telnet 服务交互的便捷机制。
3.1 连接到本地主机,运行日期命令并断开连接
require 'net/telnet'
tn = Net::Telnet.new({})
tn.login "guest", "secret"
tn.cmd "date"
# → "date\nThu Aug 26 22:38:56 CDT 2004\n% "
tn.close
# → nil
3.2 实时输出服务器响应
require 'net/telnet'
tn = Net::Telnet.new({}) {|str| print str }
tn.login("guest", "secret") {|str| print str }
tn.cmd("date") {|str| print str }
tn.close
3.3 从 NTP 服务器获取时间
require 'net/telnet'
tn = Net::Telnet.new('Host' => 'time.nonexistent.org',
'Port' => 'time',
'Timeout' => 60,
'Telnetmode' => false)
atomic_time = tn.recv(4).unpack('N')[0]
puts "Atomic time: " + Time.at(atomic_time - 2208988800).to_s
puts "Local time: " + Time.now.to_s
4. NKF:网络汉字过滤器接口
NKF 模块是 Itaru Ichikawa 的网络汉字过滤器(NKF)库(版本 1.7)的包装器。它提供了猜测 JIS、EUC 和 SJIS 流编码的功能,并可以进行编码转换。
4.1 编码常量
require 'nkf'
NKF::AUTO # → 0
NKF::JIS # → 1
NKF::EUC # → 2
NKF::SJIS # → 3
4.2 猜测字符串编码
require 'nkf'
NKF.guess("Yukihiro Matsumoto") # → 0
NKF.guess("\e$B$^$D$b$H$f$-$R$m\e(B") # → 1
NKF.guess("\244\336\244\304\244\342\244\310\244\346\244\255\244\322\244\355") # → 2
NKF.guess("\202\334\202\302\202\340\202\306\202\344\202\253\202\320\202\353") # → 3
4.3 编码转换
$ ruby -e ’p *ARGV’
"\244\336\244\304\244\342\244\310\244\346\244\255\244\322\244\355"
$ ruby -rnkf -e ’p NKF.nkf(*ARGV)’ - -Es
"\202\334\202\302\202\340\202\306\202\344\202\253\202\320\202\353"
$ ruby -rnkf -e ’p NKF.nkf(*ARGV)’ - -Ej
"\e$B$^$D$b$H$f$-$R$m\e(B"
5. Observable:观察者模式
观察者模式(也称为发布/订阅模式)提供了一种简单的机制,当一个对象(源)的状态发生变化时,通知一组感兴趣的第三方对象。在 Ruby 实现中,通知类混入
Observable
模块,该模块提供了管理关联观察者对象的方法。观察者必须实现
update
方法以接收通知。
示例代码
require 'observer'
class CheckWaterTemperature # Periodically check the water
include Observable
def run
last_temp = nil
loop do
temp = Temperature.fetch # external class...
puts "Current temperature: #{temp}"
if temp != last_temp
changed # notify observers
notify_observers(Time.now, temp)
last_temp = temp
end
end
end
end
class Warner
def initialize(&limit)
@limit = limit
end
def update(time, temp)
# callback for observer
if @limit.call(temp)
puts "--- #{time.to_s}: Temperature outside range: #{temp}"
end
end
end
checker = CheckWaterTemperature.new
checker.add_observer(Warner.new {|t| t < 80})
checker.add_observer(Warner.new {|t| t > 120})
checker.run
输出结果
Current temperature: 83
Current temperature: 75
--- Thu Aug 26 22:38:59 CDT 2004: Temperature outside range: 75
Current temperature: 90
Current temperature: 134
--- Thu Aug 26 22:38:59 CDT 2004: Temperature outside range: 134
Current temperature: 134
Current temperature: 112
Current temperature: 79
--- Thu Aug 26 22:38:59 CDT 2004: Temperature outside range: 79
6. Open - uri:将 FTP 和 HTTP 资源视为文件
Open - uri 库扩展了
Kernel#open
,允许它接受 FTP 和 HTTP 的 URI 以及本地文件名。打开后,这些资源可以像本地文件一样处理,使用常规的 IO 方法进行访问。
示例代码
require 'open-uri'
require 'pp'
open('http://localhost/index.html') do |f|
puts "URI: #{f.base_uri}"
puts "Content-type: #{f.content_type}, charset: #{f.charset}"
puts "Encoding: #{f.content_encoding}"
puts "Last modified: #{f.last_modified}"
puts "Status: #{f.status.inspect}"
pp f.meta
puts "----"
3.times {|i| puts "#{i}: #{f.gets}" }
end
输出结果
URI: http://localhost/index.html
Content-type: text/html, charset: iso-8859-1
Encoding:
Last modified: Wed Jul 18 23:44:21 UTC 2001
Status: ["200", "OK"]
{"vary"=>"negotiate,accept-language,accept-charset",
"last-modified"=>"Wed, 18 Jul 2001 23:44:21 GMT",
"content-location"=>"index.html.en",
"date"=>"Fri, 27 Aug 2004 03:38:59 GMT",
"etag"=>"\"6657-5b0-3b561f55;411edab5\"",
"content-type"=>"text/html",
"content-language"=>"en",
"server"=>"Apache/1.3.29 (Darwin)",
"content-length"=>"1456",
"tcn"=>"choice",
"accept-ranges"=>"bytes"}
----
0: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
1:
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2: <html xmlns="http://www.w3.org/1999/xhtml">
7. Open3:运行子进程并连接到所有流
Open3 库用于在子进程中运行命令。写入标准输入的数据可以被子进程读取,子进程中写入标准输出和标准错误的数据可以在
stdout
和
stderr
流中获取。
示例代码
require 'open3'
Open3.popen3('bc') do | stdin, stdout, stderr |
Thread.new { loop { puts "Err stream: #{stderr.gets}" } }
Thread.new { loop { puts "Output stream: #{stdout.gets}" } }
stdin.puts "3 * 4"
stdin.puts "1 / 0"
stdin.puts "2 ^ 5"
sleep 0.1
end
输出结果
Output stream: 12
Err stream:
Runtime error (func=(main), adr=3): Divide by zero
Output stream: 32
Err stream:
8. OpenSSL:SSL 库
Ruby 的 OpenSSL 扩展包装了免费的 OpenSSL 库,提供了安全套接层和传输层安全(SSL 和 TLS)协议,允许在网络上进行安全通信。
8.1 访问安全网站
require 'net/https'
USER = "xxx"
PW = "yyy"
site = Net::HTTP.new("www.securestuff.com", 443)
site.use_ssl = true
response = site.get2("/cgi-bin/cokerecipe.cgi",
'Authorization' => 'Basic ' +
["#{USER}:#{PW}"].pack('m').strip)
8.2 创建使用 SSL 的套接字
require 'socket'
require 'openssl'
socket = TCPSocket.new("www.secure-stuff.com", 443)
ssl_context = OpenSSL::SSL::SSLContext.new()
unless ssl_context.verify_mode
warn "warning: peer certificate won't be verified this session."
ssl_context.verify_mode = OpenSSL::SSL::VERIFY_NONE
end
sslsocket = OpenSSL::SSL::SSLSocket.new(socket, ssl_context)
sslsocket.sync_close = true
sslsocket.connect
sslsocket.puts("GET /secret-info.shtml")
while line = sslsocket.gets
p line
end
9. OpenStruct:开放(动态)结构
OpenStruct 是一种开放结构,其属性在首次赋值时动态创建。
示例代码
require 'ostruct'
os = OpenStruct.new( "f1" => "one", :f2 => "two" )
os.f3 = "cat"
os.f4 = 99
os.f1 # → "one"
os.f2 # → "two"
os.f3 # → "cat"
os.f4 # → 99
10. OptionParser:选项解析
OptionParser 是一种灵活且可扩展的方式,用于解析命令行参数。
示例代码
require 'optparse'
require 'date'
# Add Dates as a new option type
OptionParser.accept(Date, /(\d+)-(\d+)-(\d+)/) do |d, mon, day, year|
Date.new(year.to_i, mon.to_i, day.to_i)
end
opts = OptionParser.new
opts.on("-x") {|val| puts "-x seen" }
opts.on("-s", "--size VAL", Integer) {|val| puts "-s #{val}" }
opts.on("-a", "--at DATE", Date) {|val| puts "-a #{val}" }
my_argv = [ "--size", "1234", "-x", "-a", "12-25-2003", "fred", "wilma" ]
rest = opts.parse(*my_argv)
puts "Remainder = #{rest.join(', ')}"
puts opts.to_s
输出结果
-s 1234
-x seen
-a 2003-12-25
Remainder = fred, wilma
Usage: myprog [options]
-x
-s, --size VAL
-a, --at DATE
Option 定义参数表
| 参数形式 | 说明 |
|---|---|
| “-x” “-xARG” “-x=ARG” “-x[OPT]” “-x[=OPT]” “-x PLACE” | 选项有短名称 x。第一种形式无参数,接下来两种有强制参数,再接下来两种有可选参数,最后一种指定参数跟随选项。短名称也可以指定为范围(如 “-[a - c]”) |
| “–switch” “–switch=ARG” “–switch=[OPT]” “–switch PLACE” | 选项有长名称 switch。第一种形式无参数,第二种有强制参数,第三种有可选参数,最后一种指定参数跟随开关 |
| “–no - switch” | 定义一个默认值为 false 的选项 |
| “=ARG” “=[OPT]” |
此选项的参数是强制或可选的。例如,以下代码表示有一个由 -x、-y 和 -z 别名表示的选项,它接受一个强制参数,在使用信息中显示为 N:
opt.on("-x", "-y", "-z", "=N")
|
| “description” | 任何不以 - 或 = 开头的字符串都用作此选项在摘要中的描述。可以给出多个描述,它们将显示在额外的行上 |
| “/pattern/” | 任何参数必须匹配给定的模式 |
| array | 参数必须是数组中的值之一 |
| proc or method |
参数类型转换由给定的 proc 或方法执行(而不是使用
on
或
def
方法调用关联的块)
|
| ClassName |
参数必须与为 ClassName 定义的匹配,ClassName 可以是预定义的或使用
OptionParser.accept
添加的。内置参数类包括:Object(任何字符串,不转换,默认)、String(任何非空字符串,不转换)、Integer(Ruby/C 风格的整数,可选符号,0ddd 是八进制,0bddd 是二进制,0xddd 是十六进制,转换为 Integer)、Float(浮点数格式,转换为 Float)、Numeric(通用数字格式,整数转换为 Integer,浮点数转换为 Float)、Array(参数必须是由逗号分隔的字符串列表)、OptionParser::DecimalInteger(十进制整数,转换为 Integer)、OptionParser::OctalInteger(Ruby/C 风格的八进制/十六进制/二进制整数)、OptionParser::DecimalNumeric(十进制整数/浮点数,整数转换为 Integer,浮点数转换为 Float)、TrueClass, FalseClass(布尔开关)
|
11. ParseDate:解析日期字符串
ParseDate 模块定义了一个方法
ParseDate.parsedate
,用于将日期和/或时间字符串转换为表示日期和/或时间组成部分的 Fixnum 值数组。
示例
| 字符串 | 猜测参数 | 年 | 月 | 日 | 时 | 分 | 秒 | 时区 | 星期 |
|---|---|---|---|---|---|---|---|---|---|
| 1999 - 09 - 05 23:55:21 + 0900 | F | 1999 | 9 | 5 | 23 | 55 | 21 | + 0900 | – |
| 1983 - 12 - 25 | F | 1983 | 12 | 25 | – | – | – | – | – |
| 1965 - 11 - 10 T13:45 | F | 1965 | 11 | 10 | 13 | 45 | – | – | – |
| 10/9/75 1:30pm | F | 75 | 10 | 9 | 13 | 30 | – | – | – |
| 10/9/75 1:30pm | T | 1975 | 10 | 9 | 13 | 30 | – | – | – |
| Wed Feb 2 17:15:49 CST 2000 | F | 2000 | 2 | 2 | 17 | 15 | 49 | CST | 3 |
| Tue, 02 - Mar - 99 11:20:32 GMT | F | 99 | 3 | 2 | 11 | 20 | 32 | GMT | 2 |
| Tue, 02 - Mar - 99 11:20:32 GMT | T | 1999 | 3 | 2 | 11 | 20 | 32 | GMT | 2 |
| 12 - January - 1990, 04:00 WET | F | 1990 | 1 | 12 | 4 | 0 | – | WET | – |
| 4/3/99 | F | 99 | 4 | 3 | – | – | – | – | – |
| 4/3/99 | T | 1999 | 4 | 3 | – | – | – | – | – |
| 10th February, 1976 | F | 1976 | 2 | 10 | – | – | – | – | – |
| March 1st, 84 | T | 1984 | 3 | 1 | – | – | – | – | – |
| Friday | F | – | – | – | – | – | – | – | 5 |
12. Pathname:文件路径表示
Pathname 表示文件的绝对或相对名称,有两个主要用途:一是允许操作文件路径的各个部分,二是作为
Dir
、
File
和
FileTest
模块中某些方法的外观,将调用转发给由 Pathname 对象命名的文件。
12.1 路径名操作
require 'pathname'
p1 = Pathname.new("/usr/bin")
# → #<Pathname:/usr/bin>
p2 = Pathname.new("ruby")
# → #<Pathname:ruby>
p3 = p1 + p2
# → #<Pathname:/usr/bin/ruby>
p4 = p2 + p1
# → #<Pathname:/usr/bin>
p3.parent
# → #<Pathname:/usr/bin>
p3.parent.parent
# → #<Pathname:/usr>
p1.absolute?
# → true
p2.absolute?
# → false
p3.split
# → [#<Pathname:/usr/bin>, #<Pathname:ruby>]
p5 = Pathname.new("testdir")
# → #<Pathname:testdir>
p5.realpath
# → #<Pathname:/Users/dave/Work/rubybook/testdir>
p5.children
# → [#<Pathname:testdir/config.h>, #<Pathname:testdir/main.rb>]
12.2 Pathname 作为文件和目录状态请求的代理
require 'pathname'
p1 = Pathname.new("/usr/bin/ruby")
p1.file?
# → true
p1.directory?
# → false
p1.executable?
# → true
p1.size
# → 1913444
p2 = Pathname.new("testfile")
# → #<Pathname:testfile>
p2.read
# → "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
p2.readlines
# → ["This is line one\n", "This is line two\n", "This is line three\n", "And so on...\n"]
13. PP:漂亮打印对象
PP 使用
PrettyPrint
库来格式化 Ruby 对象的检查结果。它定义了一个全局函数
pp
,其工作方式类似于现有的
p
方法,但会格式化输出。
13.1 比较 “p” 和 “pp”
require 'pp'
Customer = Struct.new(:name, :sex, :dob, :country)
cust = Customer.new("Walter Wall", "Male", "12/25/1960", "Niue")
puts "Regular print"
p cust
puts "\nPretty print"
pp cust
输出结果
Regular print
#<struct Customer name="Walter Wall", sex="Male", dob="12/25/1960", country="Niue">
Pretty print
#<struct Customer
name="Walter Wall",
sex="Male",
dob="12/25/1960",
country="Niue">
13.2 避免重复显示对象
require 'pp'
a = "string"
b = [ a ]
c = [ b, b ]
PP.sharing_detection = false
pp c
PP.sharing_detection = true
pp c
输出结果
[["string"], ["string"]]
[["string"], [...]]
综上所述,这些 Ruby 库为开发者提供了丰富的功能,涵盖了邮件处理、网络连接、日期解析、文件操作等多个方面,能够帮助开发者更高效地完成各种编程任务。
14. 总结与应用建议
14.1 各库功能总结
| 库名称 | 主要功能 |
|---|---|
| Net::POP | 访问 POP 邮件服务器,获取和删除邮件 |
| Net::SMTP | 使用 SMTP 协议发送电子邮件 |
| Net::Telnet | 实现 Telnet 客户端,与非 Telnet 服务交互 |
| NKF | 猜测 JIS、EUC 和 SJIS 流编码并进行转换 |
| Observable | 实现观察者模式,状态变化时通知观察者 |
| Open - uri | 将 FTP 和 HTTP 资源视为文件进行操作 |
| Open3 | 运行子进程并连接到所有流 |
| OpenSSL | 提供 SSL 和 TLS 协议,实现安全网络通信 |
| OpenStruct | 动态创建对象属性 |
| OptionParser | 灵活解析命令行参数 |
| ParseDate | 解析日期和时间字符串 |
| Pathname | 操作文件路径,代理文件和目录状态请求 |
| PP | 漂亮打印 Ruby 对象 |
14.2 应用场景建议
-
邮件处理
:如果需要从 POP 服务器获取邮件或使用 SMTP 发送邮件,可分别使用
Net::POP和Net::SMTP库。例如,开发邮件客户端时,Net::POP可用于接收邮件,Net::SMTP可用于发送邮件。 -
网络连接
:
Net::Telnet适用于需要与 Telnet 服务或非 Telnet 服务进行交互的场景,如远程服务器管理。OpenSSL则用于实现安全的网络通信,如访问 HTTPS 网站。 -
编码处理
:当处理包含不同编码的文本时,
NKF库可以帮助猜测和转换编码,确保文本的正确显示。 -
设计模式
:
Observable模块实现的观察者模式,适用于需要在对象状态变化时通知其他对象的场景,如监控系统中温度变化的通知。 -
文件操作
:
Open - uri允许将网络资源视为文件进行操作,方便获取远程文件。Pathname则用于处理文件路径,进行路径操作和文件状态查询。 -
命令行解析
:
OptionParser提供了灵活的命令行参数解析功能,适用于开发命令行工具。 -
日期解析
:
ParseDate模块可将各种日期和时间字符串解析为标准的日期和时间组件,方便进行日期处理。 -
对象打印
:
PP库可以将 Ruby 对象以更美观的格式打印出来,便于调试和查看对象信息。
14.3 开发流程建议
以下是一个简单的 mermaid 流程图,展示了在开发过程中选择合适库的基本流程:
graph TD;
A[确定开发需求] --> B{需求类型};
B -->|邮件处理| C(Net::POP/Net::SMTP);
B -->|网络连接| D(Net::Telnet/OpenSSL);
B -->|编码处理| E(NKF);
B -->|设计模式| F(Observable);
B -->|文件操作| G(Open - uri/Pathname);
B -->|命令行解析| H(OptionParser);
B -->|日期解析| I(ParseDate);
B -->|对象打印| J(PP);
15. 注意事项与常见问题
15.1 注意事项
-
依赖问题
:部分库可能依赖于其他库或外部工具,如
OpenSSL依赖于 OpenSSL 库。在使用这些库之前,需要确保相关依赖已正确安装。 -
编码兼容性
:在使用
NKF进行编码转换时,要注意源编码和目标编码的兼容性,避免出现乱码问题。 -
资源管理
:使用
Net::POP、Net::SMTP、Net::Telnet等网络相关库时,要及时关闭连接,释放资源,避免资源泄漏。
15.2 常见问题及解决方法
| 问题描述 | 可能原因 | 解决方法 |
|---|---|---|
| 邮件发送失败 | SMTP 服务器配置错误、认证失败 | 检查 SMTP 服务器地址、端口、用户名和密码是否正确 |
| Telnet 连接失败 | 服务器地址或端口错误、服务器未开启 Telnet 服务 | 检查服务器地址和端口,确保服务器开启 Telnet 服务 |
| 编码转换后出现乱码 | 源编码猜测错误、目标编码不支持 | 检查源编码,确保目标编码支持转换 |
| 观察者未收到通知 |
观察者未实现
update
方法、
changed
方法未调用
|
确保观察者实现了
update
方法,在状态变化时调用
changed
方法
|
16. 未来发展与趋势
16.1 安全性增强
随着网络安全的重要性日益增加,
OpenSSL
等安全相关库将不断发展,提供更强大的加密算法和安全机制,以应对日益复杂的网络攻击。
16.2 功能扩展
各库可能会不断扩展功能,以满足开发者日益多样化的需求。例如,
Net::SMTP
可能会支持更多的邮件发送协议和认证方式。
16.3 与其他技术的集成
Ruby 库可能会与其他热门技术进行更紧密的集成,如与云计算、大数据等领域的技术结合,为开发者提供更全面的解决方案。
16.4 性能优化
为了提高开发效率和程序性能,各库将不断进行性能优化,减少资源消耗,提高响应速度。
17. 结语
Ruby 提供的这些丰富的库为开发者提供了强大的工具,能够帮助开发者更高效地完成各种编程任务。通过深入了解这些库的功能和使用方法,开发者可以根据具体需求选择合适的库,提高开发效率和代码质量。同时,关注这些库的未来发展趋势,能够使开发者更好地适应不断变化的技术环境,为开发出更优秀的软件奠定基础。在实际开发过程中,要注意各库的使用细节和注意事项,避免出现常见问题,确保程序的稳定性和可靠性。
超级会员免费看

63

被折叠的 条评论
为什么被折叠?



