当前位置: 首页>>编程示例 >>用法及示例精选 >>正文


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