IO

IO类实现了基本的输出输入功能。

超类:

包含的模块:

ruby 1.8 特性: File::Constants已经脱离了File

类方法:

IO.new(fd[, mode])
IO.for_fd(fd[, mode]) ((<ruby 1.7 特性>))
IO.open(fd[, mode]) ((<ruby 1.7 特性>))
IO.open(fd[, mode]) {|io| ... } ((<ruby 1.7 特性>))

生成并返回一个全新的IO对象,它对应于已打开的文件描述符fd。若生成IO对象失败的话,将引发Errno::EXXX异常。

可以采用与File.open相同的形式来为mode指定一个IO模式(但只能是字符串形式)。详情请参考内部函数openmode的默认值为 "r"。

ruby 1.7 特性: IO.for_fd与IO.new相同。IO.open稍有不同,因为它可以带块(块运行结束时fd会被关闭)。

带块的IO.open返回块的结果。其他的返回生成的IO对象。

ruby 1.8 特性: 指定mode的方法与open,File.open完全相同。(也就是说,在1.8以后的版本中,可以使用File::RDONLY等常数(数值)来指定mode)

IO.foreach(path[, rs]) {|line| ... }

path所指文件的各行内容进行迭代操作(与open一样,若path以"|"开头的话则读取命令输出)。其运作情形如下。

port = open(path)
begin
  port.each_line {|line|
     ...
  }
ensure
  port.close
end

若成功打开path就返回nil。若失败则引发Errno::EXXX异常。

使用rs所指字符串进行行的切分,rs的默认值取自内部变量$/

若将rs指定为nil,则意味着忽略行的切分。若指定为空字符串""的话,将把连续的换行当作行的切分符(段落模式)。

IO.pipe

执行pipe(2)后返回一个数组,该数组包括2个互联的IO对象。若没有成功生成IO对象的话,将引发Errno::EXXX异常。

返回数组中的首元素负责读取,第二个元素负责读入。

p pipe = IO.pipe    # => [#<IO:0x401b90f8>, #<IO:0x401b7718>]
pipe[1].puts "foo"
p pipe[0].gets      # => "foo\n"
IO.popen(command [, mode])
IO.popen(command [, mode]) {|io| ... }

command作为子进程来运行,然后建立一条连接到该进程的输入输出的管线(pipeline)。mode指定打开IO端口的模式(欲知mode详情,请参考open)。省略时将使用默认值 "r"。

返回生成的管道(IO对象)。

p io = IO.popen("cat", "r+")  # => #<IO:0x401b75c8>
io.puts "foo"
p io.gets  # => "foo\n"

若带块时,将以生成的IO对象为参数来运行该块,并返回其结果。在块得到运行以后,生成的管道将会自动关闭。

p IO.popen("cat", "r+") {|io|
  io.puts "foo"
  io.gets
}
# => "foo\n"

当命令名为"-"时,Ruby将运行fork(2)来建立一个连接到子进程的输入输出的管线。此时,父进程将返回IO对象,子进程返回nil。若带块的话,父进程以生成的IO对象为参数来运行该块并返回其结果。(管道被关闭)子进程以nil为参数来运行该块然后终止运行。

# 不带块的例子

io = IO.popen("-", "r+")
if io.nil?
  # child
  s = gets
  print "child output: " + s
  exit
end

# parent
io.puts "foo"
p io.gets                   # => "child output: foo\n"
io.close

# 带块的例子

p IO.popen("-", "r+") {|io|
  if io
    # parent
    io.puts "foo"
    io.gets
  else
    # child
    s = gets
    puts "child output: " + s
  end
}
# => "child output: foo\n"

若没有成功生成管道或子进程时,将引发Errno::EXXX异常。

ruby 1.9 特性: 若command为数组则不必通过shell即可运行子进程。

IO.read(path,[length,[offset]]) ((<ruby 1.7 特性>))

path所指文件中,从offset位置开始读入length字节的内容并将其返回。其运作情形如下。

port = open(path)
port.pos = offset if offset
begin
  port.read length
ensure
  port.close
end

lengthnil或被省略时,将一直读到EOF。

若IO已经到达EOF时则返回nil

若无法打开path,或者设定offset所指位置失败,又或者无法读入文件内容时,都将引发Errno::EXXX异常。若length为负数,则会引发ArgumentError异常。

IO.readlines(path[, rs])

读入path所指文件的全部内容后,以行为单位将其转化为数组并返回该数组。若IO已经到达EOF时返回空数组[]。

其运作情形如下。

port = open(path)
begin
  port.readlines
ensure
  port.close
end

使用rs所指字符串进行行的切分,rs的默认值取自内部变量$/

若将rs指定为nil,则意味着忽略行的切分。若指定为空字符串""的话,将把连续的换行当作行的切分符(段落模式)。

若无法打开path或者读取文件失败时,将引发Errno::EXXX异常。

IO.select(reads[, writes[, excepts[, timeout]]])

执行select(2)。传递给reads/writes/excepts的是等待输入的IO(或其子类)的实例的数组。

timeout可以是整数、Float或nil(省略时的默认值)。指定为nil时,将会一直等到IO变成就绪状态。

timeout时将返回nil,除此以外将返回一个包含3个元素的数组,这3个元素分别是等待输入/输出/异常的对象的数组(指定数组的子集)。

select相同。

IO.sysopen(path[, mode [, perm]]) ((<ruby 1.7 特性>))

打开path所指文件并返回文件描述符。若无法打开文件时将引发Errno::EXXX异常。

参数mode, perm的具体情况与内部函数open相同。

如果不使用IO.for_fd等来转化为IO对象的话,就无法关闭使用该方法打开的文件。

方法:

self << object

输出object。若object并非字符串时,将使用to_s方法将其变为字符串。该方法以self作为返回值,因此可以像下面这样使用一连串的<<

STDOUT << 1 << " is a " << Fixnum << "\n"

若输出失败时将引发Errno::EXXX异常。

binmode

将流变为二进制模式。该方法只在那些支持二进制模式的OS,如MSDOS中有效(除此以外将毫无反应)。若想从二进制模式恢复到普通模式时,只能重新打开。

返回self

clone
dup

返回一个全新的IO对象,该对象与receiver使用同一个IO。(请参考dup(2)来了解所用的文件描述符)。clone时self暂时被flush

对一个被冻结的IO使用clone时,同样会得到一个被冻结的IO。如果使用dup则会返回一个内容相同但未被冻结的IO。

close

关闭输入输出端口。

此后,若对该端口进行输入输出的话会引发IOError异常。进行垃圾回收时,未关闭的IO端口将被关闭。Traps:将close托付给GC

若close失败则引发Errno::EXXX异常。

self已被管道连接到进程上时,将等待该进程的结束。

返回nil

close_read

关闭读取用的IO。主要用在管道或读写两用的IO对象上。

self并非读取用IO,则引发IOError异常。

若close失败则引发Errno::EXXX异常。

返回nil

close_write

关闭写入用的IO。

self并非写入用IO,则引发IOError异常。

若close失败则引发Errno::EXXX异常。

返回nil

closed?

若端口已被关闭则返回真。

each([rs]) {|line| ... }
each_line([rs]) {|line| ... }

每次从IO端口读入1行来进行相关处理的迭代器。IO端口必须是以读模式打开的(请参考open)。

使用rs所指字符串进行行的切分,rs的默认值取自内部变量$/

若将rs指定为nil,则意味着忽略行的切分。若指定为空字符串""的话,将把连续的换行当作行的切分符(段落模式)。

返回self

each_byte {|ch| ... }

每次从IO端口读入1字节的内容。IO端口必须是以读模式打开的(请参考open)。

返回self

eof
eof?

若流(stream)到达文件末端时返回真。

fcntl(cmd[, arg])

将对IO执行系统调用fcntl。请参考fcntl(2)了解详细的功能。

arg为整数,则把它原封不动地传递给fcntl(2)。若为true以及false,则分别传递1和0。若为字符串,则会被当作pack过的结构体(structure)来传给fcntl(2)。 若省略arg时,其默认值为0。

cmd可以使用附加库fcntl.soFcntl模块所提供的值。

返回fcntl(2)的返回值。若未能成功执行fcntl(2)时,将引发Errno::EXXX异常。

fsync ((<ruby 1.7 特性>))

对写入用的IO执行系统调用fsync(2)。在flush之后(在OS级别上)将内存中尚未保存到硬盘上的数据写入硬盘。

成功就返回 0。失败则引发Errno::EXXX异常。若self并非写入用IO时,将引发IOError异常。

fileno
to_i

返回文件描述符的号码。

flush

刷新IO端口的内部缓冲区。 若self并非写入用IO时,将引发IOError异常。

返回self

getc

从IO端口读入1个字符,并返回该字符对应的Fixnum。到达EOF时返回nil。

gets([rs])

读入一行,若成功的话就返回读入的字符串。到达文件末尾时返回nil。其动作与IO#each相同,只不过该方法不进行迭代操作而已。

使用rs所指字符串进行行的切分,rs的默认值取自内部变量$/

若将rs指定为nil,则意味着忽略行的切分。若指定为空字符串""的话,将把连续的换行当作行的切分符(段落模式)。

IO#getsgets一样,将读入的字符串赋值给变量$_。

ioctl(cmd[, arg])

对IO执行系统调用ioctl,并返回其结果。请参考ioctl(2)以了解详细的功能。

arg为整数时就将其原封不动地传递给ioctl。若为字符串,则被看作pack过的结构体来传给ioctl。若省略arg或其值为nil以及false时,将传递0。若为true时将传递1。

isatty
tty?

若输出输入端口已与tty结合时,返回真。

lineno

返回当前的行号。

lineno=number

设定行号。

pid

若是由IO.popen所生成的IO端口时,则返回子进程的进程ID。除此以外返回nil。

pos
tell

返回文件指针的当前位置。

pos = n

将文件指针移动到指定位置。与io.seek(pos, IO::SEEK_SET)相同。

print([arg[, ...]])

依次将参数输出到IO端口。省略参数时将输出$_。该方法处理参数的方式与print相同(详情请参考这个方法)。

返回nil

printf(format[, arg[, ...]])

与C语言的printf一样,按照format将参数变为字符串,然后输出到self。

它与printf基本相同,只是该方法的第1个参数不能为IO,且不可省略。请参考sprintf格式化来了解处理参数的详情。

返回nil

putc(ch)

输出字符ch到self。该方法处理参数的方式与putc相同(详情请参考这个方法)。

返回ch

puts([obj[, ...]])

输出各个obj到self然后换行。该方法处理参数的方式与puts相同(详情请参考这个方法)。

返回nil

read([length])
read([length[, buf]]) ((<ruby 1.7 特性>))

若给出了length时,就读取length字节的内容,然后返回该字符串。若IO已到达EOF则返回nil。

若省略length的话,将读入EOF之前的所有内容。若IO已到达EOF则返回""。

若读取数据失败则引发Errno::EXXX异常。若length为负数则引发ArgumentError异常。

ruby 1.7 特性:若将某字符串传给第二参数的话,将使用读入的数据来覆盖该字符串对象,并返回读入的数据。若该字符串的长度刚好等于length时,将不会进行内存分配。若该字符串的长度不等于length时,将暂时把字符串的长度拉长(或缩短)到length的长度(随后又将变成实际读入数据的长度)。

若在调用read方法时使用了第二参数且数据为空的话(read返回nil时),buf将变为空字符串。

buf = "x" * 20;
io = File.open("/dev/null")
p io.read(10,buf)
p buf
=> nil
   ""
readchar

IO#getc一样,读入1个字符后返回与该字符相对应的Fixnum。若到达EOF则引发EOFError异常。

readline([rs])

IO#gets一样,读入1行后返回读入的字符串。若到达EOF则引发EOFError异常。

使用rs所指字符串进行行的切分,rs的默认值取自内部变量$/

若将rs指定为nil,则意味着忽略行的切分。若指定为空字符串""的话,将把连续的换行当作行的切分符(段落模式)。

readlinegets一样,将读入的字符串赋值给变量$_

readlines([rs])

读入所有数据后,以行为单位将其转化为数组,并返回该数组。若IO已到达EOF则返回空数组[]。

使用rs所指字符串进行行的切分,rs的默认值取自内部变量$/

若将rs指定为nil,则意味着忽略行的切分。若指定为空字符串""的话,将把连续的换行当作行的切分符(段落模式)。

readpartial(maxlen[, outbuf])

ruby 1.9 特性

从IO读入最多maxlen的数据,并返回读入的字符串。此时,若没有现成的数据的话,就会进入阻塞状态并一直等待数据的到来。若有现成的数据的话,哪怕只有1字节也不会进入阻塞状态。若将一个字符串传给第二参数outbuf的话,就会用读入的数据来覆盖该字符串,并返回读入的数据。若IO已到达EOF则引会发EOFError异常。

如果将阻塞所带来的影响减至最小的话,就可以让readpartial对管道、socket以及终端等的流(stream)作出恰当的反应。只有在下述条件均成立时,readpartial才会进入阻塞状态。

  • 被IO对象使用的stdio中的FILE结构体的缓冲区为空
  • 数据尚未到达流
  • 流变为EOF状态

当上述条件均成立时,readpartial就会进入阻塞状态,直到有数据出现或者到达EOF为止。

readpartial的结果如下。

  1. 若stdio的缓冲区不为空,则读取并返回缓冲区中的数据。
  2. 若流中有数据,则读取并返回流中的数据。
  3. 若流变成EOF状态,则引发EOFError异常。

例如,下例就是在管道中使用该方法的情形。

r, w = IO.pipe           #               stdio buffer    pipe content
w << "abc"               #               ""              "abc".
r.readpartial(4096)      #=> "abc"       ""              ""
r.readpartial(4096)      # 缓冲区和管道中都没有数据,因此进入阻塞状态

r, w = IO.pipe           #               stdio buffer    pipe content
w << "abc"               #               ""              "abc"
w.close                  #               ""              "abc" EOF
r.readpartial(4096)      #=> "abc"       ""              EOF
r.readpartial(4096)      # 发生EOFError异常

r, w = IO.pipe           #               stdio buffer    pipe content
w << "abc\ndef\n"        #               ""              "abc\ndef\n"
r.gets                   #=> "abc\n"     "def\n"         ""
w << "ghi\n"             #               "def\n"         "ghi\n"
r.readpartial(4096)      #=> "def\n"     ""              "ghi\n"
r.readpartial(4096)      #=> "ghi\n"     ""              ""

而且readpartial不受nonblock标识的影响。也就是说,即使设置了nonblock标识也会进入阻塞状态。

另外readpartial的运作情形与未设置nonblock标识的sysread非常相似。特别是当stdio的缓冲区为空时,就更是如出一辙了。

reopen(io)
reopen(name[, mode])

将自身转接到io上。类也将等同于io(请注意)。

若第一参数为字符串时,将把流转接到name所指的文件上。

第二参数的默认值为"r"。ruby 1.8 特性: 若省略第二参数时,将原封不动地继承self的模式。

返回self

rewind

将文件指针移动到头部。IO#lineno变为 0 。

seek(offset[, whence])

将文件指针由whence移动到offsetwhence的值是下列之一。

  • IO::SEEK_SET: 从文件头部开始(默认)
  • IO::SEEK_CUR: 从当前文件指针开始
  • IO::SEEK_END: 从文件尾部开始

省略whence时,其默认值为IO::SEEK_SET

若向着offset移动成功就返回0。若失败则引发Errno::EXXX异常。

stat

生成并返回一个包含文件状态的File::Stat对象。

若未能成功读取状态则引发Errno::EXXX异常。

另外请参考File#lstatFile.statFile.lstat

sync

以真和伪来表示当前的输出同步模式。当输出同步模式为真时,每次调用输出函数时都会刷新缓冲区。

sync=newstate

设定输出同步模式。newstate为真则表示同步模式,伪则表示非同步模式。返回newstate

sysread(length)
sysread(length[, buf]) ((<ruby 1.7 特性>))

使用read(2)进行输入,并返回包含输入数据的字符串。到达文件尾部时会引发EOFError异常。因其不使用stdio,所以如果和gets、getc或eof?等混合使用的话会引起意想不到的混乱。

若不能成功读取数据则引发Errno::EXXX异常。

ruby 1.7 特性:若将某字符串传给第二参数的话,将使用读入的数据来覆盖该字符串对象,并返回读入的数据。若该字符串的长度刚好等于length时,将不会进行内存分配。若该字符串的长度不等于length时,将暂时把字符串的长度拉长(或缩短)到length的长度(随后又将变成实际读入数据的长度)。

若在调用sysread方法时使用了第二参数且数据为空的话(sysread引发EOFError异常时),buf将变为空字符串。

buf = "x" * 20;
io = File.open("/dev/null")
p((io.sysread(10,buf) rescue nil))
p buf
=> nil
   ""
sysseek(offset[, whence]) ((<ruby 1.7 特性>))

lseek(2)相同。若将seeksysread, syswrite混用的话会引起混乱,此时应该使用本方法。

若对已缓冲的读取IO执行该方法时,会引起IOError异常。若对已缓冲的写入IO执行该方法时,会发出警告。

File.open("/dev/zero") {|f|
  buf = f.read(3)
  f.sysseek(0)
}
# => -:3:in `sysseek': sysseek for buffered IO (IOError)

File.open("/dev/null", "w") {|f|
  f.print "foo"
  f.sysseek(0)
}
# => -:3: warning: sysseek for buffered IO

参数的使用方法与IO#seek相同。

若向着offset位置移动成功则返回移动的位置(从文件头部算起)。若移动失败则引发Errno::EXXX异常。

syswrite(string)

使用write(2)来输出string。若string并非字符串,将使用to_s尝试将其变为字符串。本方法不使用stdio,因此如果与其他输出方法混用的话会引起意想不到的问题。

返回实际输出的字节数。若输出失败则引发Errno::EXXX异常。

to_io

返回self

ungetc(char)

送回(unreading)char。若送回2字节以上的内容,则无法保证其准确性。

返回nil

write(str)

对IO端口输出str。若str并非字符串,将使用to_s尝试将其变为字符串。

IO#syswrite之外的所有输出方法最后都会调用一个名为“write”的方法,因此替换本方法就可以改变输出函数的行为。

返回实际输出的字节数。若输出失败则引发Errno::EXXX异常。

常数

SEEK_CUR
SEEK_END
SEEK_SET

请参考IO#seek