本文简要介绍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类。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。