1.简介
2.安装
3.基本语法
4高级进阶
------继续
3.基本语法
3.16 File I/O 文件 输入/输出
Ruby 在kernel模块实现了I/O相关的方法。这些I/O 方法都是 IO 类派生的。
IO 类提供了 基本方法: read, write, gets, puts, readline, getc, and printf.
本节介绍这些基本方法。
3.16.1 The puts Statement
puts 显示变量的内容,在末尾添加新行。
#!/usr/bin/ruby val1 = "This is variable one" val2 = "This is variable two" puts val1 puts val2
结果:
This is variable one This is variable two
3.16.2 The gets Statement
gets 从标准屏幕STDIN 获取任何用户输入。
下例,显示提示输入信息,然后将用户输入接受,保存到变量,然后打印变量到STDOUT。
#!/usr/bin/ruby
puts "Enter a value :"
val = gets
puts val
结果:
zzl@zzl-VirtualBox:~/rubyprojects$ ruby demo_gets.rb Enter a value : this is what I entered this is what I entered
3.16.3 The putc Statement
putc 可以输出一次一个字符。
#!/usr/bin/ruby str = "Hello Ruby!" putc str
结果:
zzl@zzl-VirtualBox:~/rubyprojects$ ruby demo_putc.rb
H
3.16.4 The print Statement
print 与 puts 类似。唯一不同的是,puts 换行,而print 光标停在同行。
print "Hello World" print "Good Morning"
结果:
zzl@zzl-VirtualBox:~/rubyprojects$ ruby demo_print.rb Hello WorldGood Morning
3.16.5 Opening and Closing Files 打开和关闭文件
The File.new Method
用 File.new 方法创建文件对象,来读,写或读写文件,取决于mode 方式。 用File.close 关闭文件。
格式
aFile = File.new("filename", "mode") # ... process the file aFile.close
The File.open Method
File.open 方式创建新的文件对象,将文件对象赋值给一个文件。 File.open method 可以关联block,而File.new不行。
File.open("filename", "mode") do |aFile| # ... process the file end
Reading and Writing Files 对写文件
简单的I/O方法,同样适用于文件对象。
不过, I/O对象有更多访问方式。
The sysread Method
可以用sysread 读文件的内容。使用sysread读时, 可以用任何mode打开的文件。
input.txt
This is a simple text file for testing purpose.
例子:demo_sysread.rb
aFile = File.new("input.txt", "r") if aFile content = aFile.sysread(20) puts content else puts "Unable to open file!" end
将输出前20个字符,文件指针将停留在第21个字符的位置。
The syswrite Method
用 syswrite 将内容写入文件。使用 syswrite时,需要以写方式打开文件。
demo_syswrite.rb
aFile = File.new("input.txt", "r+") if aFile aFile.syswrite("ABCDEF") else puts "Unable to open file!" end
将 "ABCDEF" 写入文件。
The each_byte Method
each_byte 是文件类的方法。它总是与block关联。
aFile = File.new("input.txt", "r+") if aFile aFile.syswrite("ABCDEF") aFile.each_byte {|ch| putc ch; putc ?. } else puts "Unable to open file!" end
每个字节传给block 依次执行:
zzl@zzl-VirtualBox:~/rubyprojects$ ruby demo_eachbyte.rb
s. .a. .s.i.m.p.l.e. .t.e.x.t. .f.i.l.e. .f.o.r. .t.e.s.t.i.n.g. .p.u.r.p.o.s.e...
The IO.readlines Method
文件类是IO类的子类。IO的一些方法,也可以用来操作文件。
IO.readlines. 逐行读文件内容。 demo_readlines.rb
arr = IO.readlines("input.txt") puts arr[0] puts arr[1]
The IO.foreach Method
IO.foreach 方法也是逐行输出。它与readlines 的不同,foreach 与block 关联。不过foreach 不返回数组。
IO.foreach("input.txt"){|block| puts block}
将文件逐行传给block,执行block里的代码。
Renaming and Deleting Files
可以用rename 来重命名文件,delete 来删除文件。
重命名
# Rename a file from test1.txt to test2.txt File.rename( "test1.txt", "test2.txt" )
删除
#!/usr/bin/ruby # Delete file test2.txt File.delete("test2.txt")
File Modes and Ownership 文件模式及拥有者
使用chmod 及参数 mask 改变文件的模式或权限。
file = File.new( "test.txt", "w" ) file.chmod( 0755 )
这个功能和操作系统命令类似。
File Inquiries 文件查询
检查文件存在,然后打开,不存在,返回nil。
#!/usr/bin/ruby File.open("file.rb") if File::exists?( "file.rb" )
检查参数是否为文件。
#!/usr/bin/ruby # This returns either true or false File.file?( "text.txt" )
检查文件名是否是目录。
# a directory File::directory?( "/usr/local/bin" ) # => true # a file File::directory?( "file.rb" ) # => false
以下命令检查文件是否可读,可写,或可执行。
#!/usr/bin/ruby File.readable?( "test.txt" ) # => true File.writable?( "test.txt" ) # => true File.executable?( "test.txt" ) # => false
检查文件大小是否为0
#!/usr/bin/ruby File.zero?( "test.txt" ) # => true
返回文件大小
#!/usr/bin/ruby File.size?( "text.txt" ) # => 1002
返回文件类型:
#!/usr/bin/ruby File::ftype( "test.txt" ) # => file
文件类型: file, directory, characterSpecial, blockSpecial, fifo, link, socket, or unknown.
一下命令返回文件创建时间,修改时间 或最后访问时间。
#!/usr/bin/ruby File::ctime( "test.txt" ) # => Fri May 09 10:06:37 -0700 2008 File::mtime( "text.txt" ) # => Fri May 09 10:44:44 -0700 2008 File::atime( "text.txt" ) # => Fri May 09 10:45:01 -0700 2008
Directories in Ruby
文件都包含在目录里。目录可以用Dir 类来处理。
Navigating Through Directories
Dir.chdir 更改目录。
Dir.chdir("/usr/bin")
Dir.pwd 查看当前目录
puts Dir.pwd # This will return something like /usr/bin
用Dir.entries 获取指定目录里的文件和目录列表。
puts Dir.entries("/usr/bin").join(' ')
Dir.foreach 提供了 Dir.entries的类似功能。
Dir.foreach("/usr/bin") do |entry| puts entry end
也可以用Dir类的数组方式来或目录列表。
Dir["/usr/bin/*"]
Creating a Directory
Dir.mkdir 创建目录
Dir.mkdir("mynewdir")
你也可以在创建目录时,设置权限。
NOTE − mask 755 设置 owner, group, world [anyone] 为 rwxr-xr-x , r = read, w = write, and x = execute.
r,w,x分别表示读,写,执行。
Dir.mkdir( "mynewdir", 755 )
Deleting a Directory
Dir.delete 删除目录。Dir.unlink 和 Dir.rmdir执行同样功能。
Dir.delete("testdir")
Creating Files & Temporary Directories 创建文件和临时目录。
临时目录是程序执行过程中创建的但是不需要永久保存的。
Dir.tmpdir 提供当前系统的临时目录路径。虽然该方式不是默认可用。不过可以使用require 导入 'tmpdir'.
可以使用 Dir.tmpdir 和 File.join创建跨平台的临时文件
require 'tmpdir' tempfilename = File.join(Dir.tmpdir, "tingtong") tempfile = File.new(tempfilename, "w") tempfile.puts "This is a temporary file" tempfile.close File.delete(tempfilename)
上述代码创建临时文件,写入数据,然后删除。
Ruby的标准库有Tempfile, 可以创建临时文件
require 'tempfile' f = Tempfile.new('tingtong') f.puts "Hello" puts f.path f.close
Built-in Functions 内置函数
更多文件和目录,参考以下文档。
3.17 Exception 异常
执行总是会出现异常。如果你打开一个文件,但是文件并不存在,就程序没有适当地处理,沉香质量就很差。
如贵异常,程序停止。因此用异常来处理各种错误,并作适当处理以防完全停止程序。
Ruby 用 rescue 子句来处理异常。
格式
begin # - rescue OneTypeOfException # - rescue AnotherTypeOfException # - else # Other exceptions ensure # Always will be executed end
如果begin 和 rescue 之间的代码抛出异常,控制传给rescue 和 end 之间的代码。
Ruby 将异常与每个参数比较,如果匹配,则执行rescue 子句。
如果异常不匹配指定的错误类型,则可以用else 子句来处理。
demo_rescue.rb
#!/usr/bin/ruby begin file = open("/unexistant_file") if file puts "File opened successfully" end rescue file = STDIN end print file, "==", STDIN, "\n"
STDIN 赋值给file 因为rescue 之前代码执行异常。 .
zzl@zzl-VirtualBox:~/rubyprojects$ ruby demo_rescue.rb #<IO:0x0000559e61bcc208>==#<IO:0x0000559e61bcc208>
3.17.1 Using retry Statement
可以用rescue block 扑捉异常,用 retry 从头执行begin block 。
格式
begin # Exceptions raised by this code will # be caught by the following rescue clause rescue # This block will capture all types of exceptions retry # This will move control to the beginning of begin end 举例
#!/usr/bin/ruby begin file = open("/unexistant_file") if file puts "File opened successfully" end rescue fname = "existant_file" retry end
进程如下
- 打开一个不存在的文件发生异常.
- 到 rescue, fname 被重新赋值一个存在的文件。
- 通过retry, 程序回到begin 开头。
- 这次文件成功打开文件。
- 程序往下继续执行。
注意 − 如果重新赋值的文件也不存在,则会无限重试。 使用retry 时要小心。
3.17.2 Using raise Statement
使用raise 来抛出异常。
格式
raise OR raise "Error Message" OR raise ExceptionType, "Error Message" OR raise ExceptionType, "Error Message" condition
第一种简单讲当前异常重新抛出。这用于在传递前拦截异常的处理。
第二种创建一个新的RuntimeError,将message关联指定字符串。
第三种用第一个参数创建异常类型,将message 与第二个参数关联。
第四种和第三种类似,就是加了条件语句。
demo_raise1.rb
begin puts 'I am before the raise.' raise 'An error has occurred.' puts 'I am after the raise.' rescue puts 'I am rescued.' end puts 'I am after the begin block.'
结果:
I am before the raise. I am rescued. I am after the begin block. demo_raise2.rb
begin raise 'A test exception.' rescue Exception => e puts e.message puts e.backtrace.inspect end
结果:
zzl@zzl-VirtualBox:~/rubyprojects$ ruby demo_raise2.rb A test exception. ["demo_raise2.rb:2:in `<main>'"]
3.17.3 Using ensure Statement
有时候,需要在block 结束时确保某些处理执行,无论是否有异常。譬如,进入block打开文件,离开块时需要关闭文件。
ensure 子句就是来确保代码执行的。
格式
begin #.. process #..raise exception rescue #.. handle error ensure #.. finally ensure execution #.. This will always execute. end
demo_ensure.rb
begin raise 'A test exception.' rescue Exception => e puts e.message puts e.backtrace.inspect ensure puts "Ensuring execution" end
执行结果:
zzl@zzl-VirtualBox:~/rubyprojects$ ruby demo_ensure.rb A test exception. ["demo_ensure.rb:2:in `<main>'"] Ensuring execution
3.17.4 Catch and Throw
catch和throw 可以跳出深度嵌套的结构。
格式
throw :lablename #.. this will not be executed catch :lablename do #.. matching catch will be executed after a throw is encountered. end OR throw :lablename condition #.. this will not be executed catch :lablename do #.. matching catch will be executed after a throw is encountered. end
demo_catchthrow.rb
def promptAndGet(prompt) print prompt res = readline.chomp throw :quitRequested if res == "!" return res end catch :quitRequested do name = promptAndGet("Name: ") age = promptAndGet("Age: ") sex = promptAndGet("Sex: ") # .. # process information end promptAndGet("Name:")
运行此程序,手动交互。例如:
zzl@zzl-VirtualBox:~/rubyprojects$ ruby demo_catchthrow.rb Name: Ruby on Ruby Age: 5 Sex: ! Name:test
3.17.5 Class Exception
异常类:
- Interrupt
- NoMemoryError
- SignalException
- ScriptError
- StandardError
- SystemExit
还有一种异常,Fatal, 不过Ruby解释器只是内部使用此类。
如果我们自己创建异常类,需要是Exception 或它的派生类的子类。
例如
class FileSaveError < StandardError attr_reader :reason def initialize(reason) @reason = reason end end
使用以上自定义类:
File.open(path, "w") do |file| begin # Write out the data ... rescue # Something went wrong! raise FileSaveError.new($!) end end