本章我们将讨论 Ruby 中的输入&输出操作,输入是程序从键盘,文件或其他程序读取的任何数据。 输出是程序产生的数据。 输出可能会转到屏幕,文件或其他程序。
输入&输出是一个大话题。 我们提出一些示例,以使您对该主题有一个总体了解。 Ruby 中的几个类具有执行输入&输出操作的方法。 例如Kernel
,IO
,Dir
或File
。
Ruby 输出到控制台
Ruby 有几种方法可以在控制台上打印输出。 这些方法是Kernel
模块的一部分。 Kernel
的方法可用于 Ruby 中的所有对象。
#!/usr/bin/ruby
print "Apple "
print "Apple\n"
puts "Orange"
puts "Orange"
print
和puts
方法在控制台上产生文本输出。 两者之间的区别在于后者添加了新的换行符。
print "Apple "
print "Apple\n"
打印方法将两个连续的“ Apple”字符串打印到终端。 如果要创建新行,则必须显式包含换行符。 换行符为\n
。 在后台,print
方法实际上调用了要打印对象的to_s
方法。
puts "Orange"
puts "Orange"
puts
方法将两个字符串打印到控制台。 每个人都有自己的路线。 该方法自动包括换行符。
$ ./printing.rb
Apple Apple
Orange
Orange
这是 printing.rb 脚本文件的输出。
根据 Ruby 文档,print
方法与$stdout.print
等效。 $stdout
是保存标准输出流的全局变量。
#!/usr/bin/ruby
stdout.print "Ruby language\n"stdout.puts "Python language"
我们使用$stdout
变量打印两行。
Ruby 还有另外三种打印输出的方法。
#!/usr/bin/ruby
p "Lemon"
p "Lemon"
printf "There are %d apples\n", 3
putc 'K'
putc 0xA
在示例中,我们介绍了p
,printf
和putc
方法。
p "Lemon"
p
在打印对象时调用inspect
方法。 该方法对于调试很有用。
printf "There are %d apples\n", 3
printf
方法从 C 编程语言中是众所周知的。 它启用字符串格式。
putc 'K'
putc 0xA
putc
方法将一个字符打印到控制台。 第二行打印换行符。 0xA
是换行符的十六进制代码。
$ ./printing3.rb
"Lemon"
"Lemon"
There are 3 apples
K
这是printing3.rb
程序的输出。
使用内核方法将数据打印到控制台是一个快捷方式:一种打印数据的简便方法。 以下示例显示了一种将数据打印到终端的更正式的方法。
ios = IO.new STDOUT.fileno
ios.write "ZetCode\n"
ios.close
在示例中,我们打开一个标准输出流,并将一个字符串写入其中。
ios = IO.new STDOUT.fileno
new
方法返回一个我们可以向其写入数据的流。 该方法采用数字文件描述符。 STDOUT.fileno
为我们提供了标准输出流的文件描述符。 我们也可以简单地写 2。
ios.write "ZetCode\n"
我们向打开的流中写入一个字符串。
ios.close
输入流已关闭。
在 Unix 系统上,标准终端输出连接到名为/dev/tty
的特殊文件。 通过打开并写入,我们将写入控制台。
#!/usr/bin/ruby
fd = IO.sysopen "/dev/tty", "w"
ios = IO.new(fd, "w")
ios.puts "ZetCode"
ios.close
一个小的例子,我们写入/dev/tty
文件。 这仅适用于 Unix。
fd = IO.sysopen "/dev/tty", "w"
sysopen
方法打开给定路径,并返回基础文件描述符号。
ios = IO.new(fd, "w")
文件描述符号用于打开流。
ios.puts "ZetCode"
ios.close
我们向流中写入一个字符串并将其关闭。
Ruby 从控制台读取输入
在本节中,我们将创建一些代码示例,这些示例将处理从控制台读取的内容。
$stdin
是一个全局变量,其中包含标准输入的流。 它可用于从控制台读取输入。
#!/usr/bin/ruby
inp = $stdin.read
puts inp
在上面的代码中,我们使用read
方法从控制台读取输入。
inp = $stdin.read
read
方法从标准输入读取数据,直到到达文件末尾。 通过在 Unix 上按 Ctrl + D
以及在 Windows 上按 Ctrl + Z
可以产生 EOF。
$ ./reading.rb
Ruby language
Ruby language
当我们启动不带参数的程序时,脚本将从用户读取数据。 读取直到我们按 Ctrl + D
或 Ctrl + Z
为止。
$ echo "ZetCode" | ./reading.rb
ZetCode
$ ./input.rb < stones
Garnet
Topaz
Opal
Amethyst
Ruby
Jasper
Pyrite
Malachite
Quartz
如果我们进行一些重定向,脚本可以从另一个程序或文件中读取数据。
从控制台读取数据的常用方法是使用gets
方法。
#!/usr/bin/ruby
print "Enter your name: "
name = gets
puts "Hello #{name}"
我们使用gets
方法从用户读取一行。
name = gets
gets
方法从标准输入读取一行。 数据被分配给名称变量。
puts "Hello #{name}"
我们已读取的数据将打印到控制台。 我们使用插值将变量包括在字符串中。
$ ./readline.rb
Enter your name: Jan
Hello Jan
样本输出。
在以下两个脚本中,我们将讨论chomp
方法。 这是一个字符串方法,可从字符串末尾删除空格。 在执行输入操作时很有用。 方法名称和用法来自 Perl 语言。
#!/usr/bin/ruby
print "Enter a string: "
inp = gets
puts "The string has #{inp.size} characters"
我们从用户那里读取一个字符串,然后计算输入字符串的长度。
$ ./nochomp.rb
Enter a string: Ruby
The string has 5 characters
消息说该字符串有 5 个字符。 这是因为它也计入换行符。
为了获得正确的答案,我们需要删除换行符。 这是chomp
方法的工作。
#!/usr/bin/ruby
print "Enter a string: "
inp = gets.chomp
puts "The string has #{inp.size} characters"
这次我们使用chomp
方法剪切换行符。
$ ./chomp.rb
Enter a string: Ruby
The string has 4 characters
Ruby 字符串确实有 4 个字符。
Ruby 文件
从正式的 Ruby 文档中,我们了解到IO
类是 Ruby 中所有输入和输出的基础。 File
类是IO
类的唯一子类。 这两个类别紧密相关。
#!/usr/bin/ruby
f = File.open('output.txt', 'w')
f.puts "The Ruby tutorial"
f.close
在第一个示例中,我们打开一个文件并向其中写入一些数据。
f = File.open('output.txt', 'w')
我们以写模式打开文件“ output.txt”。 open
方法返回一个 io 流。
f.puts "The Ruby tutorial"
我们使用上面打开的流来写入一些数据。 puts
方法也可以用于将数据写入文件。
f.close
最后,流关闭。
$ ./simplewrite.rb
$ cat output.txt
The Ruby tutorial
我们执行脚本并显示output.txt
文件的内容。
我们将有一个类似的示例,该示例将展示其他有效的方法。
#!/usr/bin/ruby
File.open('langs', 'w') do |f|
f.puts "Ruby"
f.write "Java\n"
f << "Python\n"
end
如果open
方法之后有一个块,则 Ruby 将打开的流传递到该块。 在该块的末尾,文件将自动关闭。
f.puts "Ruby"
f.write "Java\n"
f << "Python\n"
我们使用三种不同的方法写入文件。
$ ./simplewrite2.rb
$ cat langs
Ruby
Java
Python
我们执行脚本并检查langs
文件的内容。
在第二个示例中,我们显示File
类的一些方法。
#!/usr/bin/ruby
puts File.exists? 'tempfile'
f = File.new 'tempfile', 'w'
puts File.mtime 'tempfile'
puts f.size
File.rename 'tempfile', 'tempfile2'
f.close
该示例创建一个名为tempfile
的新文件,并调用一些方法。
puts File.exists? 'tempfile'
exists?
方法检查具有给定名称的文件是否已经存在。 该行返回 false,因为我们尚未创建文件。
f = File.new 'tempfile', 'w'
文件已创建。
puts File.mtime 'tempfile'
mtime
方法为我们提供了文件的最后修改时间。
puts f.size
我们确定文件大小。 由于尚未写入文件,因此该方法返回 0。
File.rename 'tempfile', 'tempfile2'
最后,我们使用rename
方法重命名文件。
$ ./testfile.rb
false
2011-11-05 16:19:36 +0100
0
这是一个示例输出。
接下来,我们将从磁盘上的文件中读取数据。
#!/usr/bin/ruby
f = File.open("stones")
while line = f.gets do
puts line
end
f.close
这是一个简单的脚本,它将打开一个名为 stone 的文件,并将其内容逐行打印到终端。
f = File.open("stones")
我们打开一个stones
文件。 默认模式是读取模式。 stones
文件包含九个有价值的宝石名称,每个名称都位于单独的行上。
while line = f.gets do
puts line
end
gets
方法从 I / O 流中读取一行。 当我们到达文件末尾时,while 块结束。
$ ./readlines2.rb
Garnet
Topaz
Opal
Amethyst
Ruby
Jasper
Pyrite
Malachite
Quartz
这是示例的输出。
下一个示例将从文件中读取数据。
#!/usr/bin/ruby
fname = 'alllines.rb'
File.readlines(fname).each do |line|
puts line
end
该脚本显示了读取文件内容的另一种方法。 该代码示例将在终端上打印其自己的代码。
File.readlines(fname).each do |line|
puts line
end
readlines
从指定文件读取所有行,并以数组形式返回它们。 我们使用each
方法遍历数组并将行打印到终端。
$ ./alllines.rb
#!/usr/bin/ruby
fname = 'alllines.rb'
File.readlines(fname).each do |line|
puts line
end
示例的输出。
Ruby 目录
在本节中,我们使用目录。 我们有一个Dir
类,可以在 Ruby 中使用目录。
#!/usr/bin/ruby
Dir.mkdir "tmp"
puts Dir.exists? "tmp"
puts Dir.pwd
Dir.chdir "tmp"
puts Dir.pwd
Dir.chdir '..'
puts Dir.pwd
Dir.rmdir "tmp"
puts Dir.exists? "tmp"
在脚本中,我们使用Dir
类的四种方法。
Dir.mkdir "tmp"
mkdir
方法创建一个名为tmp
的新目录。
puts Dir.exists? "tmp"
使用exists?
方法,我们检查文件系统中是否存在具有给定名称的目录。
puts Dir.pwd
pwd
方法打印当前工作目录。 这是我们启动脚本的目录。
Dir.chdir '..'
chdir
方法更改到另一个目录。 ..
目录是当前工作目录的父目录。
Dir.rmdir "tmp"
puts Dir.exists? "tmp"
最后,我们使用rmdir
方法删除目录。 这次exists?
方法返回 false。
$ ./dirs.rb
true
/home/vronskij/programming/ruby/io
/home/vronskij/programming/ruby/io/tmp
/home/vronskij/programming/ruby/io
false
这是示例的输出。
在第二个示例中,我们检索目录的所有条目,包括其文件和子目录。
#!/usr/bin/ruby
fls = Dir.entries '.'
puts fls.inspect
entries
方法返回给定目录的所有条目。
fls = Dir.entries '.'
puts fls.inspect
我们得到当前目录的文件和目录数组。 .
字符在此上下文中表示当前工作目录。 inspect
方法为我们提供了更可读的数组表示形式。
$ ./allfiles.rb
["putc.rb", "simplewrite.rb", "readlines2.rb", "fileexists.rb~" ...
在输出中,我们可以看到文件和目录的数组。
第三个示例使用主目录。 计算机中的每个用户都有一个分配给他的唯一目录。 它称为主目录。 在这里,他可以放置文件并创建自己的目录层次结构。
#!/usr/bin/ruby
puts Dir.home
puts Dir.home 'root'
该脚本打印两个主目录。
puts Dir.home
如果未指定用户名,则返回当前用户的主目录。 当前用户是脚本文件的所有者。 有人启动了脚本。
puts Dir.home 'root'
在这里,我们打印特定用户的主目录:在本例中为超级用户。
$ ./homedir.rb
/home/vronskij
/root
这是一个示例输出。
Ruby 执行外部程序
Ruby 有几种执行外部程序的方法。 我们将处理其中一些问题。 在我们的示例中,我们将使用众所周知的 Linux 命令。 Windows 或 Mac 的阅读器可以使用特定于其系统的命令。
#!/usr/bin/ruby
data = system 'ls'
puts data
我们调用ls
命令列出目录内容。
data = system 'ls'
system
命令在子 Shell 中执行外部程序。 该方法属于Kernel
Ruby 模块。
$ ./system.rb
allfiles.rb characters.rb fileexists.rb homedir.rb~ ...
我们展示了另外两种在 Ruby 中运行外部程序的方式。
#!/usr/bin/ruby
out = `pwd`
puts out
out = %x[uptime]
puts out
out = %x[ls | grep 'readline']
puts out
要运行外部程序,我们可以使用反引号或%x[]
字符。
out = `pwd`
在这里,我们使用反引号执行pwd
命令。 该命令返回当前工作目录。
out = %x[uptime]
在这里,我们获得uptime
命令的输出,该命令指示系统运行了多长时间。
out = %x[ls | grep 'readline']
我们也可以结合使用命令。
$ ./system2.rb
/home/vronskij/programming/ruby/io
22:50:50 up 5:32, 1 user, load average: 0.46, 0.44, 0.45
readline.rb
readline.rb~
readlines2.rb
readlines2.rb~
我们可以使用open
方法执行命令。 该方法属于Kernel
模块。 它创建一个连接到给定流,文件或子流程的 IO 对象。 如果要连接到子进程,请使用管道字符|
来启动open
的路径。
#!/usr/bin/ruby
f = open("|ls -l |head -3")
out = f.read
puts out
f.close
puts $?.success?
在示例中,我们打印ls -l | head -3
命令的结果。 这两个命令的组合返回ls -l
命令的前三行。 我们还检查子进程的状态。
f = open("|ls -l |head -3")
我们连接到由这两个命令创建的子流程。
out = f.read
puts out
我们从子流程读取并打印数据。
f.close
我们关闭文件处理程序。
puts $?.success?
$?
是一个特殊的 Ruby 变量,它设置为最后执行的子进程的状态。 如果子进程以 OK 结束,则success?
方法返回 true。
$ ./system3.rb
total 148
-rwxr-xr-x 1 vronskij vronskij 57 2011-10-30 23:33 allfiles.rb
-rwxr-xr-x 1 vronskij vronskij 58 2011-10-30 23:33 allfiles.rb~
true
Ruby 重定向标准输出
Ruby 具有用于标准输入,标准输出和标准错误输出的预定义全局变量。 $stdout
是标准输出的变量的名称。
#!/usr/bin/ruby
stdout = File.open "output.log", "a"
puts "Ruby"
puts "Java"stdout.close
$stdout = STDOUT
puts "Python"
在上面的示例中,我们将标准输出重定向到 output.log 文件。
$stdout = File.open "output.log", "a"
此行创建一个新的标准输出。 现在,标准输出将流到ouput.log
文件。 该文件以追加模式打开。 如果该文件尚不存在,则会创建它。 否则,它将被打开并将数据写入文件的末尾。
puts "Ruby"
puts "Java"
我们打印两个字符串。 字符串将不会像往常一样显示在终端中。 相反,它们将被附加到output.log
文件中。
$stdout.close
处理程序已关闭。
$stdout = STDOUT
puts "Python"
我们使用预定义的标准常量STDOUT
重新创建正常的标准输出。 “ Python”字符串被打印到控制台。