Ruby 簡明教程 Part 8

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

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章