Ruby 简明教程

Ruby - File I/O

Ruby 提供了在内核模块中实现的整套 I/O 相关方法。所有 I/O 方法都派生自类 IO。

Ruby provides a whole set of I/O-related methods implemented in the Kernel module. All the I/O methods are derived from the class IO.

类 IO 提供所有基本方法,如 read、write、gets、puts、readline、getc 和 printf。

The class IO provides all the basic methods, such as read, write, gets, puts, readline, getc, and printf.

本章将介绍 Ruby 中可用的所有基本 I/O 函数。有关更多函数,请参阅 Ruby 类 IO。

This chapter will cover all the basic I/O functions available in Ruby. For more functions, please refer to Ruby Class IO.

The puts Statement

在前面的章节中,您已将值分配给变量,然后使用 puts 语句打印输出。

In the previous chapters, you have assigned values to variables and then printed the output using puts statement.

puts 语句指示程序显示存储在变量中的值。这会在每行末尾添加一行。

The puts statement instructs the program to display the value stored in the variable. This will add a new line at the end of each line it writes.

Example

#!/usr/bin/ruby

val1 = "This is variable one"
val2 = "This is variable two"
puts val1
puts val2

这会产生以下结果 −

This will produce the following result −

This is variable one
This is variable two

The gets Statement

gets 语句可用于从称为 STDIN 的标准屏幕接受用户的任何输入。

The gets statement can be used to take any input from the user from standard screen called STDIN.

Example

以下代码向您展示如何使用 gets 语句。此代码将提示用户输入值,该值将存储在变量 val 中,最后将打印在 STDOUT 中。

The following code shows you how to use the gets statement. This code will prompt the user to enter a value, which will be stored in a variable val and finally will be printed on STDOUT.

#!/usr/bin/ruby

puts "Enter a value :"
val = gets
puts val

这会产生以下结果 −

This will produce the following result −

Enter a value :
This is entered value
This is entered value

The putc Statement

与将整个字符串输出到屏幕上的 puts 语句不同, putc 语句可用于一次输出一个字符。

Unlike the puts statement, which outputs the entire string onto the screen, the putc statement can be used to output one character at a time.

Example

以下代码的输出仅为字符 H −

The output of the following code is just the character H −

#!/usr/bin/ruby

str = "Hello Ruby!"
putc str

这会产生以下结果 −

This will produce the following result −

H

The print Statement

print 语句与 puts 语句相似。唯一的区别是 puts 语句在打印内容后转到下一行,而 print 语句会将光标定位在同一行。

The print statement is similar to the puts statement. The only difference is that the puts statement goes to the next line after printing the contents, whereas with the print statement the cursor is positioned on the same line.

Example

#!/usr/bin/ruby

print "Hello World"
print "Good Morning"

这会产生以下结果 −

This will produce the following result −

Hello WorldGood Morning

Opening and Closing Files

到目前为止,你一直在对标准输入和输出进行读写。接下来,我们将了解如何使用实际数据文件。

Until now, you have been reading and writing to the standard input and output. Now, we will see how to play with actual data files.

The File.new Method

可根据模式字符串,使用 File.new 方法创建 File 对象以进行读、写或两者兼而有之的操作。最后,可使用 File.close 方法关闭该文件。

You can create a File object using File.new method for reading, writing, or both, according to the mode string. Finally, you can use File.close method to close that file.

Syntax

aFile = File.new("filename", "mode")
   # ... process the file
aFile.close

The File.open Method

可使用 File.open 方法创建一个新文件对象并将该文件对象指定给一个文件。但是,在 File.open 和 File.new 方法之间有一个区别。区别在于 File.open 方法可以与一个代码块关联,但你不能使用 File.new 方法执行相同的操作。

You can use File.open method to create a new file object and assign that file object to a file. However, there is one difference in between File.open and File.new methods. The difference is that the File.open method can be associated with a block, whereas you cannot do the same using the File.new method.

File.open("filename", "mode") do |aFile|
   # ... process the file
end

Reading and Writing Files

我们用于“简单”I/O 的相同方法可用于所有文件对象。因此, gets 从标准输入读取一行,而 aFile.gets 从文件对象 aFile 中读取一行。

The same methods that we’ve been using for 'simple' I/O are available for all file objects. So, gets reads a line from standard input, and aFile.gets reads a line from the file object aFile.

不过,I/O 对象提供了另外一组访问方法,使我们的生活更轻松。

However, I/O objects provides additional set of access methods to make our lives easier.

The sysread Method

可使用 sysread 方法读取文件的内容。使用 sysread 方法时,你可以在任何模式下打开文件。例如 −

You can use the method sysread to read the contents of a file. You can open the file in any of the modes when using the method sysread. For example −

以下为输入文本文件 −

Following is the input text file −

This is a simple text file for testing purpose.

现在,我们尝试读取此文件 −

Now let’s try to read this file −

#!/usr/bin/ruby

aFile = File.new("input.txt", "r")
if aFile
   content = aFile.sysread(20)
   puts content
else
   puts "Unable to open file!"
end

此语句将输出文件的前 20 个字符。文件指针现在将置于文件中的第 21 个字符。

This statement will output the first 20 characters of the file. The file pointer will now be placed at the 21st character in the file.

The syswrite Method

可使用 syswrite 方法向文件中写入内容。使用 syswrite 方法时,需要以写入模式打开文件。例如 −

You can use the method syswrite to write the contents into a file. You need to open the file in write mode when using the method syswrite. For example −

#!/usr/bin/ruby

aFile = File.new("input.txt", "r+")
if aFile
   aFile.syswrite("ABCDEF")
else
   puts "Unable to open file!"
end

此语句将“ABCDEF”写入文件。

This statement will write "ABCDEF" into the file.

The each_byte Method

此方法属于 File 类。each_byte 方法始终与一个代码块相关联。考虑以下代码示例 −

This method belongs to the class File. The method each_byte is always associated with a block. Consider the following code sample −

#!/usr/bin/ruby

aFile = File.new("input.txt", "r+")
if aFile
   aFile.syswrite("ABCDEF")
   aFile.each_byte {|ch| putc ch; putc ?. }
else
   puts "Unable to open file!"
end

字符逐个传递给变量 ch,然后按如下方式显示在屏幕上 −

Characters are passed one by one to the variable ch and then displayed on the screen as follows −

s. .a. .s.i.m.p.l.e. .t.e.x.t. .f.i.l.e. .f.o.r. .t.e.s.t.i.n.g. .p.u.r.p.o.s.e...
.
.

The IO.readlines Method

File 类是 IO 类的子类。IO 类也有一些方法可用于操作文件。

The class File is a subclass of the class IO. The class IO also has some methods, which can be used to manipulate files.

IO 类方法之一是 IO.readlines。此方法按行返回文件的内容。以下代码显示了方法 IO.readlines 的用法 −

One of the IO class methods is IO.readlines. This method returns the contents of the file line by line. The following code displays the use of the method IO.readlines −

#!/usr/bin/ruby

arr = IO.readlines("input.txt")
puts arr[0]
puts arr[1]

在此代码中,变量 arr 是一个数组。文件 input.txt 的每一行将成为数组 arr 中的一个元素。因此, arr[0] 将包含第一行,而 arr[1] 将包含文件的第二行。

In this code, the variable arr is an array. Each line of the file input.txt will be an element in the array arr. Therefore, arr[0] will contain the first line, whereas arr[1] will contain the second line of the file.

The IO.foreach Method

此方法也行行返回输出。foreach 方法和 readlines 方法之间的区别在于 foreach 方法具有区块。但与 readlines 方法不同的是,foreach 方法不会返回数组。例如 −

This method also returns output line by line. The difference between the method foreach and the method readlines is that the method foreach is associated with a block. However, unlike the method readlines, the method foreach does not return an array. For example −

#!/usr/bin/ruby

IO.foreach("input.txt"){|block| puts block}

此代码将文件 test 的内容逐行传递给变量 block,然后在屏幕上显示输出。

This code will pass the contents of the file test line by line to the variable block, and then the output will be displayed on the screen.

Renaming and Deleting Files

你可以使用重命名和删除方法富有编程性地用 Ruby 重命名和删除文件。

You can rename and delete files programmatically with Ruby with the rename and delete methods.

以下是重命名一个现有文件 test1.txt 的示例 −

Following is the example to rename an existing file test1.txt −

#!/usr/bin/ruby

# Rename a file from test1.txt to test2.txt
File.rename( "test1.txt", "test2.txt" )

以下是删除一个现有文件 test2.txt 的示例 −

Following is the example to delete an existing file test2.txt −

#!/usr/bin/ruby

# Delete file test2.txt
File.delete("test2.txt")

File Modes and Ownership

使用 chmod 方法带有掩码,来更改文件的模式或权限/访问列表 −

Use the chmod method with a mask to change the mode or permissions/access list of a file −

以下是更改一个现有文件 test.txt 的模式为掩码值的一个示例 −

Following is the example to change mode of an existing file test.txt to a mask value −

#!/usr/bin/ruby

file = File.new( "test.txt", "w" )
file.chmod( 0755 )

File Inquiries

以下命令测试在打开一个文件之前它是否存在 −

The following command tests whether a file exists before opening it −

#!/usr/bin/ruby

File.open("file.rb") if File::exists?( "file.rb" )

以下命令查询文件是否确实是一个文件 −

The following command inquire whether the file is really a file −

#!/usr/bin/ruby

# This returns either true or false
File.file?( "text.txt" )

以下命令找出给定文件名是否是一个目录 −

The following command finds out if the given file name is a directory −

#!/usr/bin/ruby

# a directory
File::directory?( "/usr/local/bin" ) # => true

# a file
File::directory?( "file.rb" ) # => false

以下命令找出文件是否可读、可写或可执行 −

The following command finds whether the file is readable, writable or executable −

#!/usr/bin/ruby

File.readable?( "test.txt" )   # => true
File.writable?( "test.txt" )   # => true
File.executable?( "test.txt" ) # => false

以下命令找出文件大小是否为零 −

The following command finds whether the file has zero size or not −

#!/usr/bin/ruby

File.zero?( "test.txt" )      # => true

以下命令返回文件的大小 −

The following command returns size of the file −

#!/usr/bin/ruby

File.size?( "text.txt" )     # => 1002

以下命令可用于找出文件类型 −

The following command can be used to find out a type of file −

#!/usr/bin/ruby

File::ftype( "test.txt" )     # => file

ftype 方法通过返回以下项之一来识别文件类型 − file、directory、characterSpecial、blockSpecial、fifo、link、socket 或 unknown。

The ftype method identifies the type of the file by returning one of the following − file, directory, characterSpecial, blockSpecial, fifo, link, socket, or unknown.

以下命令可用于查找文件何时被创建、修改或最后一次访问 −

The following command can be used to find when a file was created, modified, or last accessed −

#!/usr/bin/ruby

File::ctime( "test.txt" ) # => Fri May 09 10:06:37 -0700 2008
File::mtime( "text.txt" ) # => Fri May 09 10:44:44 -0700 2008
File::atime( "text.txt" ) # => Fri May 09 10:45:01 -0700 2008

Directories in Ruby

所有文件都包含在各个目录中,而 Ruby 处理这些目录也不成问题。File 类可以处理文件,Dir 类可以处理目录。

All files are contained within various directories, and Ruby has no problem handling these too. Whereas the File class handles files, directories are handled with the Dir class.

Navigating Through Directories

要在 Ruby 程序中更改目录,请按如下方式使用 Dir.chdir。此示例将当前目录更改为 /usr/bin。

To change directory within a Ruby program, use Dir.chdir as follows. This example changes the current directory to /usr/bin.

Dir.chdir("/usr/bin")

你可以使用 Dir.pwd 找出当前目录 −

You can find out what the current directory is with Dir.pwd −

puts Dir.pwd # This will return something like /usr/bin

你可以使用 Dir.entries 在特定目录内获取文件和目录的列表——

You can get a list of the files and directories within a specific directory using Dir.entries −

puts Dir.entries("/usr/bin").join(' ')

Dir.entries 返回一个数组,其中包含指定目录内的所有条目。Dir.foreach 提供相同的功能——

Dir.entries returns an array with all the entries within the specified directory. Dir.foreach provides the same feature −

Dir.foreach("/usr/bin") do |entry|
   puts entry
end

获取目录列表的更简洁的方法是使用 Dir 类的数组方法——

An even more concise way of getting directory listings is by using Dir’s class array method −

Dir["/usr/bin/*"]

Creating a Directory

Dir.mkdir 可用于创建目录——

The Dir.mkdir can be used to create directories −

Dir.mkdir("mynewdir")

你还可以使用 mkdir 设置新目录(不是已存在的目录)的权限——

You can also set permissions on a new directory (not one that already exists) with mkdir −

NOTE ——掩码 755 设置权限所有者、组、世界 [任何人] 为 rwxr-xr-x,其中 r = 读,w = 写,x = 执行。

NOTE − The mask 755 sets permissions owner, group, world [anyone] to rwxr-xr-x where r = read, w = write, and x = execute.

Dir.mkdir( "mynewdir", 755 )

Deleting a Directory

Dir.delete 可用于删除目录。Dir.unlink 和 Dir.rmdir 执行完全相同的功能,并且为了方便而提供。

The Dir.delete can be used to delete a directory. The Dir.unlink and Dir.rmdir performs exactly the same function and are provided for convenience.

Dir.delete("testdir")

Creating Files & Temporary Directories

临时文件是指在程序执行期间短暂创建的文件,但不是信息的永久存储。

Temporary files are those that might be created briefly during a program’s execution but aren’t a permanent store of information.

Dir.tmpdir 提供当前系统上临时目录的路径,虽然该方法默认不可用。要使 Dir.tmpdir 可用,需要使用 require 'tmpdir'。

Dir.tmpdir provides the path to the temporary directory on the current system, although the method is not available by default. To make Dir.tmpdir available it’s necessary to use require 'tmpdir'.

你可以将 Dir.tmpdir 与 File.join 一起使用,以创建一个与平台无关的临时文件——

You can use Dir.tmpdir with File.join to create a platform-independent temporary file −

require 'tmpdir'
   tempfilename = File.join(Dir.tmpdir, "tingtong")
   tempfile = File.new(tempfilename, "w")
   tempfile.puts "This is a temporary file"
   tempfile.close
   File.delete(tempfilename)

此代码创建一个临时文件,向其中写入数据并删除它。Ruby 的标准库还包括一个名为 Tempfile 的库,它可以为你创建临时文件——

This code creates a temporary file, writes data to it, and deletes it. Ruby’s standard library also includes a library called Tempfile that can create temporary files for you −

require 'tempfile'
   f = Tempfile.new('tingtong')
   f.puts "Hello"
   puts f.path
   f.close

Built-in Functions

以下是处理文件和目录的 Ruby 内置函数——

Here are the ruby built-in functions to process files and directories −