當前位置: 首頁>>編程示例 >>用法及示例精選 >>正文


Ruby IO類用法及代碼示例

本文簡要介紹ruby語言中 IO類 的用法。

Expect 庫添加了 IO 實例方法 expect ,它的作用類似於 tcl 的 expect 擴展。

要使用此方法,您必須要求期望:

require 'expect'

請參閱 expect 了解用法。

IO 類是 Ruby 中所有輸入和輸出的基礎。一個 I/O 流可能是duplexed(即雙向),因此可能使用多個本機操作係統流。

本節中的許多示例都使用 File 類,這是 IO 的唯一標準子類。這兩個類密切相關。與 File 類一樣, Socket 庫是 IO 的子類(例如 TCPSocket UDPSocket )。

Kernel#open 方法可以為這些類型的參數創建一個 IO (或 File )對象:

  • 純字符串表示適合底層操作係統的文件名。

  • "|" 開頭的字符串表示子進程。 "|" 之後的字符串的其餘部分作為一個進程調用,並連接了適當的輸入/輸出通道。

  • 等於"|-" 的字符串將創建另一個Ruby 實例作為子進程。

IO 可以使用不同的文件模式(隻讀,write-only)和正確轉換的編碼打開。有關這些選項,請參閱 IO.new 。有關上述各種命令格式的詳細信息,請參見 Kernel#open

IO.popen Open3 庫或 Process#spawn 也可用於通過 IO 與子進程通信。

如果可能,Ruby 將在不同的操作係統約定之間轉換路徑名。例如,在 Windows 係統上,文件名 "/gumby/ruby/test.rb" 將打開為 "\gumby\ruby\test.rb" 。在 Ruby 字符串中指定 Windows-style 文件名時,請記住轉義反斜杠:

"C:\\gumby\\ruby\\test.rb"

我們這裏的示例將使用Unix-style 正斜杠; File::ALT_SEPARATOR 可用於獲取特定於平台的分隔符。

全局常量 ARGF (也可以作為 $< 訪問)提供了一個 IO-like 流,它允許訪問命令行中提到的所有文件(如果沒有提到文件,則為 STDIN)。提供 ARGF#path 及其別名 ARGF#filename 以訪問當前正在讀取的文件的名稱。

io/控製台

io/console 擴展提供了與控製台交互的方法。可以從 IO.console 或標準輸入/輸出/錯誤 IO 對象訪問控製台。

要求 io/console 添加以下方法:

例子:

require 'io/console'
rows, columns = $stdout.winsize
puts "Your screen is #{columns} wide and #{rows} tall"

示例文件

這裏的許多示例都使用這些文件名及其對應的文件:

  • t.txt :一個 text-only 文件,假設通過以下方式存在:

    text = <<~EOT
      This is line one.
      This is the second line.
      This is the third line.
    EOT
    File.write('t.txt', text)
  • t.dat :假定存在的數據文件:

    data = "\u9990\u9991\u9992\u9993\u9994"
    f = File.open('t.dat', 'wb:UTF-16')
    f.write(data)
    f.close
  • t.rus :一個 Russian-language 文本文件,假設通過以下方式存在:

    File.write('t.rus', "\u{442 435 441 442}")
  • t.tmp :假定 not 存在的文件。

模式

許多 IO 方法調用必須或可以為流指定 mode;模式決定如何訪問流,包括:

  • 流是隻讀的、write-only 還是讀寫的。

  • 流是位於其開頭還是結尾。

  • 流是否將數據視為 text-only 或二進製。

  • 外部和內部編碼。

指定為整數的模式

mode 是整數時,它必須是 File::Constants 中定義的模式的一個或多個(由按位或 (|) 組合):

  • File::RDONLY :以隻讀方式打開。

  • File::WRONLY :隻為寫入而打開。

  • File::RDWR : 打開讀寫。

  • File::APPEND :打開僅用於附加。

  • File::CREAT :如果文件不存在,則創建文件。

  • File::EXCL :如果給出 File::CREAT 並且文件存在,則引發異常。

例子:

File.new('t.txt', File::RDONLY)
File.new('t.tmp', File::RDWR | File::CREAT | File::EXCL)

注意: Method IO#set_encoding 不允許將模式指定為整數。

指定為字符串的模式

mode 是字符串時,它必須以下列之一開頭:

  • 'r' : 隻讀流,位於開頭;流無法更改為可寫。

  • 'w' : Write-only 流,位於開頭;流無法更改為可讀。

  • 'a' : Write-only 流,位於末尾;每次寫入都附加到末尾;流無法更改為可讀。

  • 'r+' :讀寫流,位於開頭。

  • 'w+':讀寫流,位於末尾。

  • 'a+':讀寫流,位於末尾。

對於可寫文件流(即除隻讀文件之外的任何文件流),如果文件存在則將其截斷為零,如果不存在則創建該文件。

例子:

File.open('t.txt', 'r')
File.open('t.tmp', 'w')

以下任何一項都可以作為上述任何一項的後綴:

  • 't':文本數據;將默認外部編碼設置為 Encoding::UTF_8 ;在 Windows 上,啟用 EOL 和 CRLF 之間的轉換。

  • 'b':二進製數據;將默認外部編碼設置為 Encoding::ASCII_8BIT ;在 Windows 上,抑製 EOL 和 CRLF 之間的轉換。

如果兩者都沒有給出,則流默認為文本數據。

例子:

File.open('t.txt', 'rt')
File.open('t.dat', 'rb')

以下可以後綴到上述任何可寫模式:

  • 'x' :如果文件不存在則創建該文件;如果文件存在則引發異常。

例子:

File.open('t.tmp', 'wx')

最後,模式字符串可以指定編碼 - 僅外部編碼或外部和內部編碼 - 通過附加一個或兩個編碼名稱,用冒號分隔:

f = File.new('t.dat', 'rb')
f.external_encoding # => #<Encoding:ASCII-8BIT>
f.internal_encoding # => nil
f = File.new('t.dat', 'rb:UTF-16')
f.external_encoding # => #<Encoding:UTF-16 (dummy)>
f.internal_encoding # => nil
f = File.new('t.dat', 'rb:UTF-16:UTF-16')
f.external_encoding # => #<Encoding:UTF-16 (dummy)>
f.internal_encoding # => #<Encoding:UTF-16>

數組 Encoding.name_list 中提供了眾多編碼名稱:

Encoding.name_list.size    # => 175
Encoding.name_list.take(3) # => ["ASCII-8BIT", "UTF-8", "US-ASCII"]

編碼

設置外部編碼後,讀取的字符串在讀取時由該編碼標記,寫入的字符串在寫入時轉換為該編碼。

當同時設置外部和內部編碼時,讀取的字符串由外部編碼轉換為內部編碼,寫入的字符串由內部編碼轉換為外部編碼。有關轉碼輸入和輸出的更多詳細信息,請參閱 Encoding

如果外部編碼是 'BOM|UTF-8''BOM|UTF-16LE''BOM|UTF16-BE' ,Ruby 會檢查輸入文檔中的 Unicode BOM 以幫助確定編碼。對於 UTF-16 編碼,文件打開模式必須是二進製的。如果找到 BOM,則將其剝離並使用 BOM 中的外部編碼。

請注意,BOM-style 編碼選項不區分大小寫,因此“bom|utf-8”也是有效的。)

打開選項

許多 IO 方法接受可選參數 opts ,該參數確定如何打開新流:

  • :mode:流模式。

  • :flags:整數文件打開標誌;如果還給出了mode,則兩者為bitwise-ORed。

  • :external_encoding :流的外部編碼。

  • :internal_encoding :流的內部編碼。 '-' 是默認內部編碼的同義詞。如果值為nil,則不會發生轉換。

  • :encoding :將外部和內部編碼指定為 'extern:intern'

  • :textmode :如果為真值,則指定模式為text-only,否則為二進製。

  • :binmode :如果為真值,則指定模式為二進製,否則為text-only。

  • :autoclose :如果為真值,則指定流關閉時fd 將關閉;否則它保持打開狀態。

String#encode 中提供的選項也可用,它們可以控製外部內部編碼之間的轉換。

獲取線選項

許多 IO 方法接受可選的關鍵字參數,這些參數決定如何處理流:

  • :chomp :如果 true ,則省略行分隔符;默認為 false

位置

IO 流具有 position ,它是流中將發生下一次讀取或寫入的非負整數偏移量(以字節為單位)。

請注意,文本流可能具有多字節字符,因此位置為 n ( bytes ) 的文本流在當前位置之前可能沒有 n characters - 可能會更少。

一個新的流最初被定位:

  • 如果其模式為 'r''w''r+' ,則在開頭(位置 0 )。

  • 最後(位置 self.size )如果其模式是 'a''w+''a+'

查詢位置的方法:

從流中讀取通常會改變其位置:

f = File.open('t.txt')
f.tell     # => 0
f.readline # => "This is line one.\n"
f.tell     # => 19
f.readline # => "This is the second line.\n"
f.tell     # => 45
f.eof?     # => false
f.readline # => "Here's the third line.\n"
f.eof?     # => true

寫入流通常會改變其位置:

f = File.open('t.tmp', 'w')
f.tell         # => 0
f.write('foo') # => 3
f.tell         # => 3
f.write('bar') # => 3
f.tell         # => 6

迭代流通常會改變它的位置:

f = File.open('t.txt')
f.each do |line|
  p "position=#{f.pos} eof?=#{f.eof?} line=#{line}"
end

輸出:

"position=19 eof?=false line=This is line one.\n"
"position=45 eof?=false line=This is the second line.\n"
"position=70 eof?=true line=This is the third line.\n"

也可以通過某些其他方法更改位置:

電話號碼

可讀 IO 流具有 line number ,它是流中將發生下一次讀取的非負整數行號。

新流最初的行號為 0

方法 IO#lineno 返回行號。

從流中讀取行通常會更改其行號:

f = File.open('t.txt', 'r')
f.lineno   # => 0
f.readline # => "This is line one.\n"
f.lineno   # => 1
f.readline # => "This is the second line.\n"
f.lineno   # => 2
f.readline # => "Here's the third line.\n"
f.lineno   # => 3
f.eof?     # => true

遍曆流中的行通常會更改其行號:

f = File.open('t.txt')
f.each_line do |line|
  p "position=#{f.pos} eof?=#{f.eof?} line=#{line}"
end

輸出:

"position=19 eof?=false line=This is line one.\n"
"position=45 eof?=false line=This is the second line.\n"
"position=70 eof?=true line=This is the third line.\n"

相關用法


注:本文由純淨天空篩選整理自ruby-lang.org大神的英文原創作品 IO類。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。