IO 类

IO 类的实例(通常称为)表示底层操作系统中的输入/输出流。IO 类是 Ruby 中输入和输出的基础。

File 是 Ruby 核心中唯一一个 IO 的子类。Ruby 标准库中的一些类也是 IO 的子类;这些类包括 TCPSocketUDPSocket

全局常量 ARGF(也可以作为 $< 访问)提供了一个类似 IO 的流,允许访问 ARGV 中找到的所有文件路径(如果 ARGV 为空,则在 STDIN 中找到)。ARGF 本身不是 IO 的子类。

StringIO 提供了一个类似 IO 的流,用于处理 StringStringIO 本身不是 IO 的子类。

基于 IO 的重要对象包括

可以使用以下方法创建 IO 的实例

File 流一样,IO 流具有

与其他 IO 流一样,它还具有

扩展 io/console

扩展 io/console 提供了许多与控制台交互的方法;需要它会在 IO 类中添加许多方法。

示例文件

此处的许多示例都使用以下变量

# English text with newlines.
text = <<~EOT
  First line
  Second line

  Fourth line
  Fifth line
EOT

# Russian text.
russian = "\u{442 435 441 442}" # => "тест"

# Binary data.
data = "\u9990\u9991\u9992\u9993\u9994"

# Text file.
File.write('t.txt', text)

# File with Russian text.
File.write('t.rus', russian)

# File with binary data.
f = File.new('t.dat', 'wb:UTF-16')
f.write(data)
f.close

打开选项

许多 IO 方法接受可选的关键字参数,这些参数确定如何打开新流

还可以使用 String#encode 中提供的选项,这些选项可以控制外部编码和内部编码之间的转换。

基本 IO

您可以使用这些方法执行基本流 IO,这些方法通常对多字节字符串进行操作

位置

IO 流具有一个非负整数位置,该位置是下一个读取或写入将发生的字节偏移量。新流的位置为零(行号也为零);方法 rewind 将位置(和行号)重置为零。

这些方法会丢弃 缓冲区和用于该 IO 的 Encoding::Converter 实例。

相关方法

打开和关闭的流

新的 IO 流可以打开以进行读取、打开以进行写入或两者都打开。

当垃圾回收器回收时,流会自动关闭。

尝试在关闭的流上读取或写入会引发异常。

相关方法

流的末尾

您可以查询流是否定位在其末尾

您可以使用方法 IO#seek 重新定位到流的末尾

f = File.new('t.txt')
f.eof? # => false
f.seek(0, :END)
f.eof? # => true
f.close

或者通过读取所有流内容(这比使用 IO#seek 慢)

f.rewind
f.eof? # => false
f.read # => "First line\nSecond line\n\nFourth line\nFifth line\n"
f.eof? # => true

行 IO

IO 类支持面向行的 输入输出

行输入

IO 类支持面向行的 文件IO 流输入

文件行输入

您可以使用以下方法从文件中读取行

对于这些方法中的每一个

流式行输入

您可以使用以下方法从 IO 流中读取行

对于这些方法中的每一个

行分隔符

每个行输入方法都使用一个行分隔符:该字符串确定什么被视为一行;它有时被称为输入记录分隔符

默认的行分隔符取自全局变量 $/,其初始值为 "\n"

通常,下一个要读取的行是从当前位置到下一个行分隔符的所有数据(但请参阅特殊行分隔符值

f = File.new('t.txt')
# Method gets with no sep argument returns the next line, according to $/.
f.gets # => "First line\n"
f.gets # => "Second line\n"
f.gets # => "\n"
f.gets # => "Fourth line\n"
f.gets # => "Fifth line\n"
f.close

您可以通过传递参数 sep 来使用不同的行分隔符

f = File.new('t.txt')
f.gets('l')   # => "First l"
f.gets('li')  # => "ine\nSecond li"
f.gets('lin') # => "ne\n\nFourth lin"
f.gets        # => "e\n"
f.close

或者通过设置全局变量 $/

f = File.new('t.txt')
$/ = 'l'
f.gets # => "First l"
f.gets # => "ine\nSecond l"
f.gets # => "ine\n\nFourth l"
f.close
特殊行分隔符值

每个行输入方法都接受参数 sep 的两个特殊值

行限制

每个行输入方法都使用一个整数行限制,该限制限制了可能返回的字节数。(多字节字符不会被拆分,因此返回的行可能会略长于限制)。

默认限制值为 -1;任何负限制值都表示没有限制。

如果没有限制,则行仅由 sep 确定。

# Text with 1-byte characters.
File.open('t.txt') {|f| f.gets(1) }  # => "F"
File.open('t.txt') {|f| f.gets(2) }  # => "Fi"
File.open('t.txt') {|f| f.gets(3) }  # => "Fir"
File.open('t.txt') {|f| f.gets(4) }  # => "Firs"
# No more than one line.
File.open('t.txt') {|f| f.gets(10) } # => "First line"
File.open('t.txt') {|f| f.gets(11) } # => "First line\n"
File.open('t.txt') {|f| f.gets(12) } # => "First line\n"

# Text with 2-byte characters, which will not be split.
File.open('t.rus') {|f| f.gets(1).size } # => 1
File.open('t.rus') {|f| f.gets(2).size } # => 1
File.open('t.rus') {|f| f.gets(3).size } # => 2
File.open('t.rus') {|f| f.gets(4).size } # => 2
行分隔符和行限制

通过给定参数 seplimit,将两种行为结合起来

示例

File.open('t.txt') {|f| f.gets('li', 20) } # => "First li"
File.open('t.txt') {|f| f.gets('li', 2) }  # => "Fi"
行号

可读的 IO 流具有非负整数行号

除非通过调用方法 IO#lineno= 进行修改,否则行号是某些面向行的读取方法根据有效的行分隔符读取的行数

新流最初的行号为零(位置为零);方法 rewind 将行号(和位置)重置为零

f = File.new('t.txt')
f.lineno # => 0
f.gets   # => "First line\n"
f.lineno # => 1
f.rewind
f.lineno # => 0
f.close

从流中读取行通常会更改其行号

f = File.new('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.close

迭代流中的行通常会更改其行号

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

输出

"position=11 eof?=false lineno=1"
"position=23 eof?=false lineno=2"
"position=24 eof?=false lineno=3"
"position=36 eof?=false lineno=4"
"position=47 eof?=true lineno=5"

与流的位置不同,行号不会影响下一次读取或写入的发生位置

f = File.new('t.txt')
f.lineno = 1000
f.lineno # => 1000
f.gets   # => "First line\n"
f.lineno # => 1001
f.close

与行号关联的是全局变量 $.

行输出

您可以使用此方法逐行写入 IO 流

字符 IO

您可以使用以下方法逐字符处理 IO 流

字节 IO

您可以使用以下方法逐字节处理 IO 流

码位 IO

您可以逐个码位地处理 IO 流

这里有什么

首先,其他地方有什么。IO 类

在这里,IO 类提供了对以下方面有用的方法

创建

读取

写入

定位

迭代

设置

查询

缓冲

底层访问

其他