Ruby 在kernel模块实现了I/O相关的方法。这些I/O 方法都是 IO 类派生的。html
IO 类提供了 基本方法: read, write, gets, puts, readline, getc, and printf.数组
本节介绍这些基本方法。ruby
puts 显示变量的内容,在末尾添加新行。socket
#!/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
gets 从标准屏幕STDIN 获取任何用户输入。ui
下例,显示提示输入信息,而后将用户输入接受,保存到变量,而后打印变量到STDOUT。this
#!/usr/bin/ruby操作系统
puts "Enter a value :"指针
val = getscode
puts val
结果:
zzl@zzl-VirtualBox:~/rubyprojects$ ruby demo_gets.rb Enter a value : this is what I entered this is what I entered
putc 能够输出一次一个字符。
#!/usr/bin/ruby str = "Hello Ruby!" putc str
结果:
zzl@zzl-VirtualBox:~/rubyprojects$ ruby demo_putc.rb
H
print 与 puts 相似。惟一不一样的是,puts 换行,而print 光标停在同行。
print "Hello World" print "Good Morning"
结果:
zzl@zzl-VirtualBox:~/rubyprojects$ ruby demo_print.rb Hello WorldGood Morning
用 File.new 方法建立文件对象,来读,写或读写文件,取决于mode 方式。 用File.close 关闭文件。
aFile = File.new("filename", "mode") # ... process the file aFile.close
File.open 方式建立新的文件对象,将文件对象赋值给一个文件。 File.open method 能够关联block,而File.new不行。
File.open("filename", "mode") do |aFile| # ... process the file end
简单的I/O方法,一样适用于文件对象。
不过, I/O对象有更多访问方式。
能够用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个字符的位置。
用 syswrite 将内容写入文件。使用 syswrite时,须要以写方式打开文件。
demo_syswrite.rb
aFile = File.new("input.txt", "r+") if aFile aFile.syswrite("ABCDEF") else puts "Unable to open file!" end
将 "ABCDEF" 写入文件。
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...
文件类是IO类的子类。IO的一些方法,也能够用来操做文件。
IO.readlines. 逐行读文件内容。 demo_readlines.rb
arr = IO.readlines("input.txt") puts arr[0] puts arr[1]
IO.foreach 方法也是逐行输出。它与readlines 的不一样,foreach 与block 关联。不过foreach 不返回数组。
IO.foreach("input.txt"){|block| puts block}
将文件逐行传给block,执行block里的代码。
能够用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")
使用chmod 及参数 mask 改变文件的模式或权限。
file = File.new( "test.txt", "w" ) file.chmod( 0755 )
这个功能和操做系统命令相似。
检查文件存在,而后打开,不存在,返回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
文件都包含在目录里。目录能够用Dir 类来处理。
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/*"]
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 )
Dir.delete 删除目录。Dir.unlink 和 Dir.rmdir执行一样功能。
Dir.delete("testdir")
临时目录是程序执行过程当中建立的可是不须要永久保存的。
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
更多文件和目录,参考如下文档。
执行老是会出现异常。若是你打开一个文件,可是文件并不存在,就程序没有适当地处理,沉香质量就不好。
如贵异常,程序中止。所以用异常来处理各类错误,并做适当处理以防彻底中止程序。
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>
能够用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
进程以下
注意 − 若是从新赋值的文件也不存在,则会无限重试。 使用retry 时要当心。
使用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>'"]
有时候,须要在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
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
异常类:
还有一种异常,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