目录搜索
Ruby用户指南3、开始4、简单的例子5、字符串6、正则表达式7、数组8、回到那些简单的例子9、流程控制10、迭代器11、面向对象思维12、方法13、类14、继承15、重载方法16、访问控制17、单态方法18、模块19、过程对象20、变量21、全局变量22、实变量23、局部变量24、类常量25、异常处理:rescue26、异常处理:ensure27、存取器28、对象的初始化29、杂项RGSS入门教程1、什么是RGSS2、开始:最简单的脚本3、数据类型:数字4、数据类型:常量与变量5、数据类型:字符串6、控制语句:条件分歧语句7、控制语句:循环8、函数9、对象与类10、显示图片11、数组12、哈希表(关联数组)13、类14、数据库15、游戏对象16、精灵的管理17、窗口的管理18、活动指令19、场景类Programming Ruby的翻译Programming Ruby: The Pragmatic Programmer's Guide前言RoadmapRuby.new类,对象和变量容器Containers,块Blocks和迭代Iterators标准类型深入方法表达式Expressions异常,捕捉和抛出(已经开始,by jellen)模块基本输入输出线程和进程当遭遇挫折Ruby和它的世界Ruby和Web开发Ruby TkRuby 和微软的 Windows扩展RubyRuby语言 (by jellen)类和对象 (by jellen)Ruby安全反射Reflection内建类和方法标准库OO设计网络和Web库Windows支持内嵌文档交互式Ruby Shell支持Ruby参考手册Ruby首页卷首语Ruby的启动环境变量对象执行结束时的相关处理线程安全模型正则表达式字句构造程序变量和常数字面值操作符表达式控制结构方法调用类/方法的定义内部函数内部变量内部常数内部类/模块/异常类附加库Ruby变更记录ruby 1.6 特性ruby 1.7 特性Ruby术语集Ruby的运行平台pack模板字符串sprintf格式Marshal格式Ruby FAQRuby的陷阱
文字

基本输入输出



Ruby提供了两种I/O例程,第一种是简单的接口,我们已经用了很多了。

print "Enter your name: "
name = gets

Kernel模块提供了一整套和I/O相关的方法:gets, open, print, printf, putc, puts, readline, readlines, 和test等,这些方法能使你简单方便的进行Ruby编程。这些方法典型的对标准输入输出进行操作,很适合编写过滤器等。

另一方面,ruby提供了IO对象,让我们可以对io进行更多的控制。

什么是IO对象?

Ruby defines a single base class, IO, to handle input and output. This base class is subclassed by classes File and BasicSocket to provide more specialized behavior, but the principles are the same throughout. An IO object is a bidirectional channel between a Ruby program and some external resource.[For those who just have to know the implementation details, this means that a single IO object can sometimes be managing more than one operating system file descriptor. For example, if you open a pair of pipes, a single IO object contains both a read pipe and a write pipe.] There may be more to an IO object than meets the eye, but in the end you still simply write to it and read from it.

In this chapter, we'll be concentrating on class IO and its most commonly used subclass, class File. For more details on using the socket classes for networking, see the section beginning on page 469.

Opening and Closing Files

As you might expect, you can create a new file object using File.new .

aFile = File.new("testfile", "r")

# ... process the file

aFile.close

You can create a File object that is open for reading, writing, or both, according to the mode string (here we opened ``testfile'' for reading with an ``r''). The full list of allowed modes appears on page 326. You can also optionally specify file permissions when creating a file; see the description of File.new on page 303 for details. After opening the file, we can work with it, writing and/or reading data as needed. Finally, as responsible software citizens, we close the file, ensuring that all buffered data is written and that all related resources are freed.

But here Ruby can make life a little bit easier for you. The method File.open also opens a file. In regular use, it behaves just like File.new . However, if there's a block associated with the call, open behaves differently. Instead of returning a new File object, it invokes the block, passing the newly opened File as a parameter. When the block exits, the file is automatically closed.

File.open("testfile", "r") do |aFile|

# ... process the file

end

Reading and Writing Files

The same methods that we've been using for ``simple'' I/O are available for all file objects. So, gets reads a line from standard input, and aFile.gets reads a line from the file object aFile.

However, I/O objects enjoy an additional set of access methods, all intended to make our lives easier.

Iterators for Reading

As well as using the usual loops to read data from an IO stream, you can also use various Ruby iterators. IO#each_byte invokes a block with the next 8-bit byte from the IO object (in this case, an object of type File).

aFile = File.new("testfile")
aFile.each_byte {|ch| putc ch; putc ?. }
produces:
T.h.i.s. .i.s. .l.i.n.e. .o.n.e.
.T.h.i.s. .i.s. .l.i.n.e. .t.w.o.
.T.h.i.s. .i.s. .l.i.n.e. .t.h.r.e.e.
.A.n.d. .s.o. .o.n.......
.

IO#each_line calls the block with the next line from the file. In the next example, we'll make the original newlines visible using String#dump , so you can see that we're not cheating.

aFile.each_line {|line| puts "Got #{line.dump}" }
produces:
Got "This is line one\n"
Got "This is line two\n"
Got "This is line three\n"
Got "And so on...\n"

You can pass each_line any sequence of characters as a line separator, and it will break up the input accordingly, returning the line ending at the end of each line of data. That's why you see the ``\n'' characters in the output of the previous example. In the next example, we'll use ``e'' as the line separator.

aFile.each_line("e") do |line|
  puts "Got #{ line.dump }"
end
produces:
Got "This is line"
Got " one"
Got "\nThis is line"
Got " two\nThis is line"
Got " thre"
Got "e"
Got "\nAnd so on...\n"

If you combine the idea of an iterator with the auto-closing block feature, you get IO.foreach . This method takes the name of an I/O source, opens it for reading, calls the iterator once for every line in the file, and then closes the file automatically.

IO.foreach("testfile") { |line| puts line }
produces:
This is line one
This is line two
This is line three
And so on...

Or, if you prefer, you can retrieve an entire file into an array of lines:

arr = IO.readlines("testfile")
arr.length ?/td> 4
arr[0] ?/td> "This is line one\n"

Don't forget that I/O is never certain in an uncertain world---exceptions will be raised on most errors, and you should be ready to catch them and take appropriate action.

Writing to Files

So far, we've been merrily calling puts and print, passing in any old object and trusting that Ruby will do the right thing (which, of course, it does). But what exactly is it doing?

The answer is pretty simple. With a couple of exceptions, every object you pass to puts and print is converted to a string by calling that object's to_s method. If for some reason the to_s method doesn't return a valid string, a string is created containing the object's class name and id, something like <ClassName:0x123456>.

The exceptions are simple, too. The nil object will print as the string ``nil,'' and an array passed to puts will be written as if each of its elements in turn were passed separately to puts.

What if you want to write binary data and don't want Ruby messing with it? Well, normally you can simply use IO#print and pass in a string containing the bytes to be written. However, you can get at the low-level input and output routines if you really want---have a look at the documentation for IO#sysread and IO#syswrite on page 335.

And how do you get the binary data into a string in the first place? The two common ways are to poke it in byte by byte or to use Array#pack .

str = "" ?/td> ""
str << 1 << 2 << 3 ?/td> "\001\002\003"
[ 4, 5, 6 ].pack("c*") ?/td> "\004\005\006"

But I Miss My C++ Iostream

Sometimes there's just no accounting for taste...However, just as you can append an object to an Array using the << operator, you can also append an object to an output IO stream:

endl = "\n"
$stdout << 99 << " red balloons" << endl
produces:
99 red balloons

Again, the << method uses to_s to convert its arguments to strings before sending them on their merry way.

与网络交互

Ruby支持很多网络协议,不管是高层的还是底层的。

ruby提供了一些基本类,让你可以使用TCP,UDP,SOCKS等很多协议交互,而不必拘泥在网络层。这些类也提供了辅助类,让你可以轻松的对服务器进行读写。这个例子利用finger协议查询用户oracle的信息:

require 'socket'
client = TCPSocket.open('localhost', 'finger')
client.send("oracle\n", 0)    # 0 means standard packet
puts client.readlines
client.close
结果:
Login: oracle         			Name: Oracle installation
Directory: /home/oracle             	Shell: /bin/bash
Never logged in.
No Mail.
No Plan.

对于高层,lib/net里面提供了一些与应用层协议(FTP,HTTP,POP,SMTP,TELNET)等交互的库模块。比如,下面的例子列出了Pragmatic Programmer主页里的图像。

require 'net/http'

h = Net::HTTP.new('www.pragmaticprogrammer.com', 80) resp, data = h.get('/index.html', nil) if resp.message == "OK"   data.scan(/<img src="(.*?)"/) { |x| puts x } end
produces:
images/title_main.gif
images/dot.gif
images/dot.gif
images/dot.gif
images/aafounders_70.jpg
images/pp_cover_thumb.png
images/ruby_cover_thumb.png
images/dot.gif
images/dot.gif


Extracted from the book "Programming Ruby - The Pragmatic Programmer's Guide"
Copyright © 2001 by Addison Wesley Longman, Inc. This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, v1.0 or later (the latest version is presently available at http://www.opencontent.org/openpub/)).

Distribution of substantively modified versions of this document is prohibited without the explicit permission of the copyright holder.

Distribution of the work or derivative of the work in any standard (paper) book form is prohibited unless prior permission is obtained from the copyright holder.
上一篇:下一篇: