HOWTO · Ruby
在 Ruby 中读取文件的行
Ruby 使用两种不同的方法读取文件的行。
本页内容
Ruby 提供两种按行读取本地文本文件的实用方法。File.readlines 会将各行收集到数组中;File.foreach 则在读取每一行时将其传给代码块。根据需求选择:需要完整的行集合,还是可以逐行立即处理。
使用 File.readlines 读取所有行
File.readlines 会为每一行返回一个字符串,并将这些字符串组成数组。如果需要检查完整集合、反复遍历各行,或按数组索引访问某一行,可以使用它。每个字符串通常会保留行结束符;如果处理或显示文本时不需要行结束符,可以调用 chomp。
运行以下示例:
本节中的代码以及显示的标签或输出仍为英文。
require "tempfile"
Tempfile.create("ruby-lines") do |file|
file.write("First item\nSecond item\nThird item\n")
file.flush
lines = File.readlines(file.path)
lines.each do |line|
puts line.chomp
end
end
使用临时文件可以让示例自成一体。在自己的程序中,将文件路径替换为本地文件的路径。返回的数组会将所有行字符串保留在内存中,因此文件越大,占用的内存通常也越多。对于较小的文件,或需要按索引访问行的情况,这种取舍通常很方便。如果文件很大,而且只需扫描一次,可以改为逐行处理。
使用 File.foreach 逐行读取
File.foreach 会打开文件,并将每一行传给指定的代码块。它不会创建并返回包含全部行的数组;每次执行完代码块后,程序可以继续处理下一行。当文件很大,而你不需要保留每一行时,这种方式适合筛选、计数或转换内容。
运行以下示例:
本节中的代码以及显示的标签或输出仍为英文。
require "tempfile"
Tempfile.create("ruby-lines") do |file|
file.write("First item\nSecond item\nThird item\n")
file.flush
File.foreach(file.path) do |line|
puts line.chomp
end
end
如果行带有结束符,代码块收到的行也会包含该结束符。chomp 会移除末尾的换行符(以及适用时的回车符与换行符组合),但不会移除行末的其他字符。如果需要保留原始行结束符,可以直接处理 line。在代码块迭代期间,File.foreach 会负责打开和关闭文件,即使代码块提前退出也一样。
选择合适的方法并处理常见情况
如果任务需要数组,例如要访问 lines[1] 或多次遍历收集到的行,可以使用 File.readlines。如果只需遍历一次,并希望避免将整个文件保留在内存中,可以使用 File.foreach。两种方法没有一种在所有情况下都更好;合适的选择取决于文件大小和具体处理需求。
如果路径不存在,或程序没有读取权限,两种方法都可能失败。应在能够给出有用反馈的地方处理预期会发生的文件系统错误。例如,遇到路径不存在时,可以通过 rescue 提示找不到输入文件;权限错误则可以单独按 Errno::EACCES 处理。避免不加区分地捕获所有异常,因为这可能会掩盖程序错误。
如果只需按位置选取某些行,使用 File.readlines 可以方便地通过数组索引访问,但它仍会读取整个文件。如果需要查找符合条件的行,File.foreach 可以通过 break 提前停止;找到所需结果后,就不必继续扫描文件。这里的两个示例都读取本地文件;读取 URL 需要使用其他 API,不在本指南讨论范围内。