IO(input/output) 即输入输出对象。
在程序启动时就会分配三个IO对象,分别为标出输入、标准输出和错误输出。
$stdin
STDIN
$stdout
STDOUT
$stderr
STDERR
检查标准输入是否为屏幕
$stdin.tty?
File
IO的子类,主要用于文件的输出和输入。
io = File.open(file[, mode[, perm]][, opt])
io = open(file[, mode[, perm]][, opt])
file.close
通过 File.open 方法或 open 方法打开文件并获取新的 IO 对象。
mode
模式(mode)会指定以何种目的打开文件(表 17.1)。缺省模式为只读模式("r")。在 Windows 环境下,在各模式后加上 b,通过 "rb"、"rb+" 等形式即可表示二进制模式(后述)。Windows 以 外的平台会忽略 b 模式,不过为了便于辨别目标文件的类型,建议操作二进制文件时还是使用 b 模式。像 "rt" 这样,在各模式末尾加上 t,会将读写时的换行符统一为 \n。
模式 | 意义 |
---|---|
"r" | 用只读模式打开文件 |
"r+" | 用读写模式打开文件 |
"w" | 用只写模式打开文件。文件不存在则创建新的文件;文件已存在则清空文件,即将文件大小设置为 0 |
"w+" | 读写模式,其余同 "w" |
"a" | 用追加模式打开文件。文件不存在则创建新的文件 |
"a+" | 用读取 / 追加模式打开文件。文件不存在则创建新的文件 |
File.read(file[, length [, offset]])): 不创建file对象直接读取file里的数据.
File.binread(file[, length[, offset]]):已二进制的方式读取文件。
File.write(file[, data[, offset]]):不创建文件直接向file写入数据。
File.binwrite(file[, data[, offset]]):以二进制模式打开写入file。
File.expand_path("ruby", "/usr/bin"):join路径
Dir
Dir 修改当前工作目录
当前工作目录
puts Dir.pwd
#chdir
Dir.chdir("/var/spool/mail")
puts Dir.pwd
Dir.chdir("/tmp") do
puts Dir.pwd
Dir.chdir("/usr") do
puts Dir.pwd
end
puts Dir.pwd
end
puts Dir.pwd
require
/Users/willyang/.rvm/rubies/ruby-2.3.1/lib/ruby/2.3.0/rubygems/core_ext
io.gets(rs)
io.each(rs)
io.each_line(rs)
io.readlines(rs)
while line = io.gets
line.chomp!
end
p io.eof?
io.each_line do |line|
line.chomp!
end
另外,用 readlines 方法可以一次性地读取所有数据,并返回将每行数据作为元素封装的 数组。
ary = io.readlines
ary.each_line do |line|
line.chomp!
end
io.lineno: 获取行数
$stdin.each_line do |line|
printf("%3d %s", $stdin.lineno, line)
end
io.each_char: 逐个字符读取
io.each_byte:逐个字节读取
io.getc:只读取一个字符
io.ungetc(ch): 将参数 ch 指定的字符退回到 io 的输入缓冲区中
io.getbyte: 只读取一个字节
io.ungetbyte(byte): 将一个字节退回到缓冲区
io.read(size):读取参数 size 中指定的大小的数据。不指定大小时,则一次性读取全部数据并返回.
io.puts(str0, str1, ...):在字符串末尾添加换行符后输出
io.putc(ch):输出参数 ch 指定的字符编码所对应的字符,参数为字符串时输出首字符。
io.print(str0, str1, ...):输出参数指定的字符串
io.printf(fmt, arg0, arg1, ...):按照指定的格式输出字符串
io.write(str): 输出参数 s t r 指定的字符串
io<<str:输出参数 str 指定的字符串<< 会返回接收者本身,因此可以像下面这样写
io << "foo" << "bar" << "baz"
文件指针
io.pos/io.pos=(position):通过 pos 方法可以获得文件指针现在的位置
io.seek(offset, whence):移动文件指针的方法
io.rewind:将文件指针返回到文件的开头
io.truncate(size):按照参数 size 指定的大小截断文件
二进制模式与文本模式
io.binmode:使用 binmode 方法可将其变更为二进制模式
缓冲
即使对 IO 对象进行写入,结果也并不一定马上就会反映在控制台或者文件中。在使用 write、print 等方法操作 IO 对象时,程序内部会开辟出一定的空间来保存临时生成的数据副 本(图 17.2)。这部分空间就称为缓冲区(buffer)。缓冲区里累积一定量的数据后,就会进行输 出处理,然后清空缓冲区。
io.flush:调用这个方法后会立即输出输出缓冲区中的数据
io.sync/io.sync=(state): 指定io.sync = true后,同步输出内容到文件不需要flush
与命令进行交互
IO.popen(command, mode)
用 IO.popen 方法生成的 IO 对象的输入 / 输出,会关联启动的命令 command 的标准输入 / 输出。也就是说,IO 对象的输出会作为命令的输入,命令的输出则会作为 IO 对象的输入。
open("|command", mode):将带有管道符号的命令传给 open 方法的效果与使用 IO.popen 方法是一样的。
open-uri 库
除了控制台、文件以外,进程间通信时使用的管道、网络间通信时使用的套接字也都可以作 为 I O 对象使用。管道、套接字的使用方法超出了本书的范围,因此不详细说明,这里我们简单 地介绍一下利用 HTTP、FTP 从网络获取数据的方法。
require "open-uri"
# 通过HTTP读取数据 open("http://www.ruby-lang.org/zh_cn/") do |io|
puts io.read # 将Ruby的官方网页输出到控制台 end
# 通过FTP读取数据
filename = "ruby-2.3.0.tar.gz"
url = "ftp://www.ruby-lang.org/pub/ruby/2.3/#{filename}"
open(url) do |io|
File.binwrite(filename, io.read) # 写入文件
end
stringio 库
在测试程序时,虽然我们希望知道向文件或控制台输出了什么,但程序实际执行的结果却往 往很难知道。为此,可以通过向模拟 IO 对象的对象进行输出来确认执行结果。
StringIO 就是用于模拟 IO 对象的对象。通过 require 引用 stringio 库后,就可以使 用 StringIO 对象了(代码清单 17.10)。
require "stringio"
io = StringIO.new
io.puts("A")
io.puts("B")
io.puts("C")
io.rewind
p io.read #=> "A\nB\nC\n"
IO.pipe
返回对应管道两端的io对象
read_io, wirte_io = IO.pipe
wirte_io.puts '1'
# => nil
read_io.gets
# => 1
IO.popen
返回命令执行完后的输出
f = IO.popen("uname")
f.readlines
# => ["Darwin\n"]
IO.select
输入两数组的IO对象,返回包含这些IO对象的数组的数组。如果给出了可选的超时值并且在超时秒内没有准备好IO对象,它将返回nil
rp, wp = IO.pipe
mesg = "ping "
100.times {
rs, ws, = IO.select([rp], [wp])
if r = rs[0]
ret = r.read(5)
print ret
case ret
when /ping/
mesg = "pong\n"
when /pong/
mesg = "ping "
end
end
if w = ws[0]
w.write(mesg)
end
}
# =>
# ping pong
# ping pong
# ping pong
# (...)
# ping