本文簡要介紹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 IO.eof用法及代碼示例
- Ruby IO.read用法及代碼示例
- Ruby IO.fileno用法及代碼示例
- Ruby IO.pread用法及代碼示例
- Ruby IO.raw用法及代碼示例
- Ruby IO.readlines用法及代碼示例
- Ruby IO.to_i用法及代碼示例
- Ruby IO.self << object用法及代碼示例
- Ruby IO.tty?用法及代碼示例
- Ruby IO.close_write用法及代碼示例
- Ruby IO.write_nonblock用法及代碼示例
- Ruby IO.set_encoding_by_bom用法及代碼示例
- Ruby IO.syswrite用法及代碼示例
- Ruby IO.close_read用法及代碼示例
- Ruby IO.stat用法及代碼示例
- Ruby IO.pwrite用法及代碼示例
- Ruby IO.ungetc用法及代碼示例
- Ruby IO.noecho用法及代碼示例
- Ruby IO.new用法及代碼示例
- Ruby IO.sysopen用法及代碼示例
- Ruby IO.try_convert用法及代碼示例
- Ruby IO.write用法及代碼示例
- Ruby IO.pathconf用法及代碼示例
- Ruby IO.sysseek用法及代碼示例
- Ruby IO.closed?用法及代碼示例
注:本文由純淨天空篩選整理自ruby-lang.org大神的英文原創作品 IO類。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。