Ruby 檔案的輸入與輸出


Ruby 提供了一整套 I/O 相關的方法,在核心(Kernel)模組中實作。所有的 I/O 方法衍生自 IO 類別。

類別 IO 提供了所有基礎的方法,例如 read、 write、 gets、 puts、 readline、getcprintf

本章節將講解所有 Ruby 中可用的基礎的 I/O 函數。如需了解更多的函數,請查看 Ruby 的 IO 類別。

puts 語句

在前面的章節中,您賦值給變數,然後使用 puts 語句列印輸出。

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

gets 語句

gets 語句可用於取得來自名為STDIN 的標準螢幕的使用者輸入。

實例

下面的程式碼示範如何使用 gets 語句。程式碼將提示使用者輸入一個值,該值將儲存在變數 val 中,最後會列印在 STDOUT 上。

#!/usr/bin/ruby

puts "Enter a value :"
val = gets
puts val

以上實例運行輸出結果為:

Enter a value :
This is entered value
This is entered value

putc 語句

puts 語句不同,puts 語句輸出整個字串到螢幕上,而putc 語句可用於依序輸出一個字元。

實例

下面程式碼的輸出只是字元H:

#!/usr/bin/ruby

str="Hello Ruby!"
putc str

以上實例運行輸出結果為:

H

print 語句

print 語句與puts 語句類似。唯一的不同在於 puts 語句在輸出內容後會跳到下一行,而使用 print 語句時,遊標定位在同一行。

實例

#!/usr/bin/ruby

print "Hello World"
print "Good Morning"

以上實例執行輸出結果為:

Hello WorldGood Morning

#開啟和關閉檔案

截至現在,您已經讀取並寫入標準輸入和輸出。現在,我們將看看如何操作實際的資料檔案。

File.new 方法

您可以使用File.new 方法建立一個File 物件用於讀取、寫入或讀寫,讀寫權限取決於mode 參數。最後,您可以使用 File.close 方法來關閉該檔案。

語法

aFile = File.new("filename", "mode")
   # ... 处理文件
aFile.close

File.open 方法

您可以使用File.open 方法建立一個新的file 對象,並把該file 物件賦值給檔案。但是,File.openFile.new 方法之間有一點不同。不同點是 File.open 方法可與區塊關聯,而 File.new 方法不能。

File.open("filename", "mode") do |aFile|
   # ... process the file
end

下表列出了開啟檔案的不同模式:

模式描述
r只讀模式。文件指針被放置在文件的開頭。這是預設模式。
r+讀寫模式。文件指針被放置在文件的開頭。
w只寫模式。如果文件存在,則重寫文件。如果檔案不存在,則建立一個新檔案用於寫入。
w+讀寫模式。如果文件存在,則重寫已存在的文件。如果文件不存在,則建立一個新文件用於讀寫。
a只寫模式。如果文件存在,則文件指標被放置在文件的末尾。也就是說,檔案是追加模式。如果檔案不存在,則建立一個新檔案用於寫入。
a+讀寫模式。如果文件存在,則文件指標被放置在文件的末尾。也就是說,檔案是追加模式。如果文件不存在,則建立一個新文件用於讀寫。

讀取和寫入檔案

用於簡單 I/O 的方法也可用於所有 file 物件。所以,gets 從標準輸入讀取一行,aFile.gets 從檔案物件 aFile 讀取一行。

但是,I/O 物件提供了存取方法的附加設置,為我們提供了便利。

sysread 方法

您可以使用方法 sysread 來讀取檔案的內容。當使用方法 sysread 時,您可以使用任一模式開啟檔案。例如:

下面是輸入文字檔:

This is a simple text file for testing purpose.

現在讓我們試著讀取這個檔案:

#!/usr/bin/ruby

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 來寫入內容到檔案。當使用方法 syswrite 時,您需要以寫入模式開啟檔案。例如:

#!/usr/bin/ruby

aFile = File.new("input.txt", "r+")
if aFile
   aFile.syswrite("ABCDEF")
else
   puts "Unable to open file!"
end

該語句將寫入 "ABCDEF" 到檔案中。

each_byte 方法

該方法屬於類別 File。方法 each_byte 是個可以迭代字串中每個字元。請看下面的程式碼實例:

#!/usr/bin/ruby

aFile = File.new("input.txt", "r+")
if aFile
   aFile.syswrite("ABCDEF")
   aFile.rewind
   aFile.each_byte {|ch| putc ch; putc ?. }
else
   puts "Unable to open file!"
end

字元一個接著一個被傳到變數ch,然後顯示在螢幕上,如下所示:

A.B.C.D.E.F.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.readlines方法

類別File 是類別IO 的子類別。類別 IO 也有一些用於操作文件的方法。

IO.readlines 是 IO 類別中的一個方法。此方法逐行返回文件的內容。下面的程式碼顯示了方法 IO.readlines 的使用:

#!/usr/bin/ruby

arr = IO.readlines("input.txt")
puts arr[0]
puts arr[1]

在這段程式碼中,變數 arr 是一個陣列。檔案 input.txt 的每一行將是陣列 arr 中的一個元素。因此,arr[0] 將包含第一行,而 arr[1] 將包含檔案的第二行。

IO.foreach 方法

該方法也逐行傳回輸出。方法 foreach 與方法 readlines 之間不同的是,方法 foreach 與區塊相關聯。但是,不像方法 readlines,方法 foreach 不是傳回一個陣列。例如:

#!/usr/bin/ruby

IO.foreach("input.txt"){|block| puts block}

這段程式碼將把檔案 test 的內容逐行傳給變數 block,然後輸出會顯示在螢幕上。

重新命名和刪除檔案

您可以透過 renamedelete 方法重新命名和刪除檔案。

下面的實例重新命名一個已存在檔案test1.txt

#!/usr/bin/ruby

# 重命名文件 test1.txt 为 test2.txt
File.rename( "test1.txt", "test2.txt" )

下面的實例刪除一個已存在檔案test2.txt

#!/usr/bin/ruby

# 删除文件 test2.txt
File.delete("text2.txt")

檔案模式與所有權

使用帶有遮罩的chmod 方法來改變檔案的模式或權限/存取清單:

下面的實例改變一個已存在檔案test.txt 的模式為一個掩碼值:

#!/usr/bin/ruby

file = File.new( "test.txt", "w" )
file.chmod( 0755 )

下表列出了chmod 方法中可使用的不同的掩碼:

##w ,針對擁有者#0100x ,針對擁有者#0070rwx 遮罩,針對所屬群組0040r ,針對所屬群組#0020w ,針對所屬群組#0010x ,針對所屬群組#0007rwx 遮罩,針對其他人0004r ,針對其他人#0002w ,針對其他人#0001x ,針對其他人4000#執行時設定使用者ID
掩碼描述
#0700rwx 掩碼,針對擁有者
0400r ,針對擁有者
#0200
##### #2000######執行時設定所屬組ID############1000######儲存交換文本,甚至在使用後也會儲存####### ######

檔案查詢

下面的命令在開啟檔案之前檢查檔案是否已存在:

#!/usr/bin/ruby

File.open("file.rb") if File::exists?( "file.rb" )

下面的命令查詢檔案是否確實是一個檔案:

#!/usr/bin/ruby

# 返回 true 或false
File.file?( "text.txt" )

下面的命令檢查給定的檔案名稱是否是一個目錄:

#!/usr/bin/ruby

# 一个目录
File::directory?( "/usr/local/bin" ) # => true

# 一个文件
File::directory?( "file.rb" ) # => false

下面的命令檢查檔案是否可讀、可寫、可執行:

#!/usr/bin/ruby

File.readable?( "test.txt" )   # => true
File.writable?( "test.txt" )   # => true
File.executable?( "test.txt" ) # => false

下面的命令檢查文件是否大小為零:

#!/usr/bin/ruby

File.zero?( "test.txt" )      # => true

下面的指令傳回檔案的大小:

#!/usr/bin/ruby

File.size?( "text.txt" )     # => 1002

下面的指令用於檢查檔案的類型:

#!/usr/bin/ruby

File::ftype( "test.txt" )     # => file

ftype 方法透過傳回下列中的某個值來標識了檔案的類型:file、 directory、 characterSpecial、 blockSpecial、 fifo、 link、 socket 或 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

Ruby 中的目錄

所有的檔案都是包含在目錄中, Ruby 提供了處理檔案和目錄的方式。 File 類別用於處理文件,Dir 類別用於處理目錄。

瀏覽目錄

為了在 Ruby 程式中改變目錄,請使用 Dir.chdir。下面的實例改變目前目錄為 /usr/bin

Dir.chdir("/usr/bin")

您可以透過 Dir.pwd 查看目前目錄:

puts Dir.pwd # 返回当前目录,类似 /usr/bin

您可以使用Dir.entries 來取得指定目錄內的檔案和目錄列表:

puts Dir.entries("/usr/bin").join(' ')

Dir.entries 傳回一個數組,包含指定目錄內的所有項目。 Dir.foreach 提供了相同的功能:

Dir.foreach("/usr/bin") do |entry|
   puts entry
end

取得目錄清單的一個更簡潔的方式是透過使用Dir 的類別數組的方法:

Dir["/usr/bin/*"]

#建立目錄

Dir.mkdir 可用來建立目錄:

Dir.mkdir("mynewdir")

您也可以透過mkdir 在新目錄(不是已存在的目錄)上設定權限:

注意:掩碼755 設定擁有者(owner)、所屬群組(group)、每個人(world [anyone])的權限為rwxr-xr-x,其中r = read 讀取, w = write 寫入,x = execute 執行。

Dir.mkdir( "mynewdir", 755 )

刪除目錄

Dir.delete 可用來刪除目錄。 Dir.unlinkDir.rmdir 執行同樣的功能,為我們提供了便利。

Dir.delete("testdir")

建立檔案 & 暫存目錄

暫存檔案是那些在程式執行過程中被簡單地創建,但不會永久儲存的資訊。

Dir.tmpdir 提供了目前系統上暫存目錄的路徑,但是該方法預設是不可用的。為了讓 Dir.tmpdir 可用,使用必需的 'tmpdir' 是必要的。

您可以把Dir.tmpdirFile.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 中處理檔案和目錄的內建函數的完整列表:

  • File 類別和方法。

  • Dir 類別和方法。