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