Ruby 开发(九) - 文件 IO(下)

378 阅读5分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第20天,点击查看活动详情

二、读取文件

迭代读取文件

迭代行

Ruby 中的 File 类提供了两个对文件进行迭代读取的方法,each_line 和 each。这两个方法功能相同,都是一次将文件里面的每一行内容传入代码块,进行迭代。

path = "readme.txt"
file = File.new(path, "r")

file.each do |line|
  puts line
end

file.close

执行上述代码,输出结果如下:

README Content Line 1
README Content Line 2
README Content Line 3
README Content Line 4
README Content Line 5

按字节迭代

File 对象的 each_byte 可以通过字节的方式迭代文本内容

path = "readme.txt"
file = File.new(path, "r")

file.each_byte do |byte|
  print byte
end

file.close

执行上述代码,输出结果如下:

82696568776932671111101161011101163276105110101324910826965687769326711111011610111011632761051101013250108269656877693267111110116101110116327610511010132511082696568776932671111101161011101163276105110101325210826965687769326711111011610111011632761051101013253

foreach 迭代器迭代

IO 类中提供了一个类方法 foreach,可以通过 的形式迭代文件内容

path = "readme.txt"
file = File.new(path, "r")

IO.foreach(file) do |line|
  puts line
end

file.close

执行上述代码,输出内容如下:

README Content Line 1
README Content Line 2
README Content Line 3
README Content Line 4
README Content Line 5

三、写入文件

File 对象提供了以下几种写入的方法:

  • print 方法:将一行或者多行字符串写入文件,并且不换行,可以通过设置 “$\” 让每次写入换行
  • puts 方法:将一行字符串或者多行字符串写入一个文件,每次写入之后会自动换行
  • putc 方法:将一个字符写入文件,如果传入的是整数,则将整数转换为字符后写入
  • write 方法:将一行字符串写入文件

写入文件需要使用在实例化文件对象时添加写入模式(w\w+)或者追加模式(a\a+)

path = "readme.txt"
file = File.new(path, "w")

$\ = "\n"
file.puts("Zulu")
file.write("Yankee")
file.print("Xray")

file.close

file = File.new(path, "r")

IO.foreach file do |line|
  puts line
end

执行上述代码,输出结果如下:

Zulu
YankeeXray

原文件中的内容被删除,重新写入,如果追加文件内容需要用到 “a” 操作模式打开文件

path = "readme.txt"
file = File.new(path, "a")

file.print("Whiskey")

file.close

file = File.new(path, "r")

IO.foreach file do |line|
  puts line
end

file.close

执行上述代码,输出结果如下:

Zulu
YankeeXray
Whiskey

四、操作文件

删除文件

File 类的 delete 和 unlink 方法可以对文件进行删除,如果文件删除成功则返回删除的个数,否则抛出 Errno::ENOENT 异常

path = "readme.txt"

count = File.delete(path)
puts "删除文件的个数为 #{count.to_s}"

执行上述代码,输出结果如下:

删除文件的个数为 1

在文件已经被删除的情况下,再次执行删除会报错如下:

Traceback (most recent call last):
	1: from /ex14.rb:4:in `<main>'
/ex14.rb:4:in `delete': No such file or directory @ apply2files - readme.txt (Errno::ENOENT)

重命名或移动文件

File 类的 rename 方法可以对文件进行重命名,该方法接收两个字符串作为参数,一个是文件的原文件名,一个是文件的重命名后的名字

path = "readme.txt"
path_rename = "README.md"
File.rename path, path_rename

重命名时如果源文件和新文件所在位置不是同一个目录下,则相当于重命名并移动到了新的目录下

文件路径操作

File 类中内置了几个类方法,可以对文件路径进行操作,可以根据相对路径来获取绝对路径,也可以将字符组成一个新的路径。

dirname 方法和 basename 方法都可以根据路径获取目录名称和文件名称,basename 方法可以选择设置第二个参数,该参数设置的是文件中要截取的后缀,如果第二个参数设置为文件的扩展名,则返回的将是不加扩展名的文件名称。

path = "ruby-file/README.md"

puts File.dirname path
puts File.basename path
puts File.basename(path, ".md")

执行上述代码,输出结果如下:

ruby-file
README.md
README

expand_path 类方法可以获取相对路径的绝对路径

path = "ruby-file/README.md"

puts File.expand_path path

执行上述代码,输出结果如下:

/Users/username/ruby/code/ruby-file/ruby-file/README.md

join 类方法可以将字符串合并成为一个新的路径

puts File.join "ruby-file","README.md"

执行上述代码,输出结果如下:

ruby-file/README.md

五、操作目录

Ruby 中 Dir 类提供了一些内置的方法可以对目录进行操作,如获取当前目录、改变目录、删除目录以及遍历目录等操作。

获取当前目录

pwd 和 getwd 方法可以用来获取当前目录。

puts Dir.pwd
puts Dir.getwd

执行上述代码,输出结果如下:

/Users/Practice/June/ruby-file
/Users/Practice/June/ruby-file

改变当前目录

chdir 方法可以改变当前目录,该方法接收一个新目录路径作为参数,执行完以后将当前目录切换到新目录中。如果没有为该方法设置参数,那么该方法将当前目录切换到当前用户系统所在的目录。

遍历当前目录

Dir 类的 foreach 类方法可以对文件内容进行迭代,也可以通过 Dir 实例的 each 方法迭代目录中的提供,另外 Dir 还提供了一个 entries 类方法,可以直接以数组的形式返回目录中的所有内容

# 遍历目录

puts "#{Dir.pwd} 目录中的内容"

Dir.foreach(Dir.pwd) do |item|
  puts item
end

puts "-----------------"

items = Dir.new(Dir.pwd)
items.each do |item|
  puts item
end

puts "-----------------"

item_list = Dir.entries(Dir.pwd)
item_list.each do |item|
  puts item
end

执行上述代码,输出结果如下:

/ruby-file/bravo 目录中的内容
.
..
foxtrot
charlie.rb
ex22.rb
-----------------
.
..
foxtrot
charlie.rb
ex22.rb
-----------------
.
..
foxtrot
charlie.rb
ex22.rb

删除当前目录

Dir 类提供了三个类方法可用于删除:delete、rmdir 和 unlink,如果删除成功,则返回 0 ,如果目录不存在或者目录不为空则会抛出异常

在保存 ruby 文件的同级目录下新建空文件夹 alpha 和 delta,新建包含文本文件的文件夹 bravo

begin
  puts Dir.delete("alpha")
rescue Exception => e
  puts e.class
end

begin
  puts Dir.rmdir("delta")
rescue Exception => e
  puts e.class
end

begin
  puts Dir.unlink("bravo")
rescue Exception => e
  puts e.class
end

执行上述代码,输出结果如下:

0
0
Errno::ENOTEMPTY

在删除 bravo 不为空文件夹的时候报错,也就是说只能删除空文件夹。