Ruby 文件 I/O
Ruby 文件 I/O 和目录
Section titled “Ruby 文件 I/O 和目录”Ruby 提供了一套全面的 I/O(输入/输出)相关方法,主要通过 IO 类及其子类(如 File)实现。许多基本的 I/O 操作也作为 Kernel 模块中的方法提供,使得它们可以全局访问。
IO 类提供了基本方法,例如 read、write、gets、puts、readline、getc 和 printf。本章介绍 Ruby 中的基本 I/O 函数以及文件/目录操作。
标准输入/输出
Section titled “标准输入/输出”puts 语句
Section titled “puts 语句”puts(put string)将其参数写入标准输出 (STDOUT),每个参数后跟一个换行符。如果参数是一个数组,它将每个元素写在新的一行上。如果调用时没有参数,它只打印一个换行符。
#!/usr/bin/env ruby# frozen_string_literal: true
val1 = "This is variable one"val2 = "This is variable two"puts val1puts val2puts [1, 2, 3] # Prints each number on a new line输出结果为:
This is variable oneThis is variable two123gets 语句
Section titled “gets 语句”gets(get string)从标准输入 (STDIN) 读取一行输入。它返回包含末尾换行符的行,如果到达文件末尾则返回 nil。使用 chomp 移除换行符。
#!/usr/bin/env ruby# frozen_string_literal: true
puts "Enter your name:"name = getsputs "Hello, #{name.chomp}! You entered: #{name.inspect}" # .chomp 移除末尾的换行符
puts "Enter your age:"age_str = gets.chompif age_str age = age_str.to_i puts "You will be #{age + 5} in 5 years."else puts "No age entered."end示例交互:
Enter your name:AliceHello, Alice! You entered: "Alice\n"Enter your age:30You will be 35 in 5 years.putc 语句
Section titled “putc 语句”putc(put character)写入单个字符到标准输出。如果给定字符串,它写入第一个字符。如果给定整数,它写入对应于该字节值的字符。
#!/usr/bin/env ruby# frozen_string_literal: true
str = "Hello Ruby!"putc str # 输出: Hputc 65 # 输出: A ('A' 的 ASCII 值)print 语句
Section titled “print 语句”print 类似于 puts,但不会自动附加换行符。它对其参数调用 to_s 并将它们写入 STDOUT。
#!/usr/bin/env ruby# frozen_string_literal: true
print "Hello World"print " Good Morning"print "\nNext line."输出结果为:
Hello World Good MorningNext line.打开和关闭文件
Section titled “打开和关闭文件”File.open 方法用于打开文件。它可以接受一个块,这是推荐的方式,因为它确保当块完成时文件会自动关闭,即使发生错误也是如此。
# Syntax with a block (recommended)File.open("filename.txt", "mode") do |file_object| # ... process the file using file_object ...end # File is automatically closed here
# Syntax without a block (manual close needed)# aFile = File.new("filename.txt", "mode")# ... process the file ...# aFile.closeFile.new 类似于 File.open,但不接受块。
文件模式:
| 模式 | 描述 |
|---|---|
| r | 只读。从文件开头开始(默认模式)。 |
| r+ | 读写。从文件开头开始。 |
| w | 只写。截断现有文件长度为零,或创建一个新文件用于写入。 |
| w+ | 读写。截断现有文件或创建一个新文件用于读写。 |
| a | 只写(追加)。如果文件存在,则从文件末尾开始,否则创建新文件。数据总是写入文件末尾。 |
| a+ | 读写(追加)。写入时从末尾开始。读取可以从任意位置进行。如果文件不存在则创建新文件。 |
| b | 二进制文件模式(可选,可与其他模式组合,例如 “rb”, “wb+”)。在某些系统(如 Windows)上,这会影响换行符的处理。 |
读取和写入文件
Section titled “读取和写入文件”文件打开后,可以在文件对象上使用 IO 方法,例如 read、gets、puts、write。
sysread 和 syswrite 方法(低级):
Section titled “sysread 和 syswrite 方法(低级):”sysread 从文件直接读取指定数量的字节,绕过 Ruby 的内部缓冲。syswrite 用于写入。这些方法不如带缓冲的 I/O 方法常用。
#!/usr/bin/env ruby# frozen_string_literal: true
# 创建一个示例文件File.open("sample.txt", "w") { |f| f.puts "This is line one."; f.puts "This is line two." }
# Using sysreadbegin File.open("sample.txt", "r") do |file| content_chunk = file.sysread(20) # Read up to 20 bytes puts "First 20 bytes (sysread): #{content_chunk.inspect}" endrescue EOFError puts "sysread: End of file reached prematurely."end
# Using syswrite (overwrites beginning of file)begin File.open("sample.txt", "r+") do |file| bytes_written = file.syswrite("HELLO ") puts "Bytes written (syswrite): #{bytes_written}" endrescue SystemCallError => e puts "syswrite error: #{e.message}"end
# Check content after syswriteputs "Content after syswrite: #{File.read('sample.txt').inspect}"each_byte 方法:
Section titled “each_byte 方法:”遍历文件的每个字节(作为整数)。
#!/usr/bin/env rubyFile.open("sample.txt", "r") do |file| puts "sample.txt 中的字节:" file.each_byte { |byte| print "#{byte.chr}." if byte < 128 } # 打印可显示的 ASCII 字符 putsendIO.readlines 和 File.readlines 方法:
Section titled “IO.readlines 和 File.readlines 方法:”将整个文件读取到一个字符串数组中,数组的每个元素是文件中的一行(包含换行符)。对于非常大的文件请谨慎使用,因为它会将所有内容加载到内存中。
#!/usr/bin/env ruby# frozen_string_literal: true
begin lines_array = File.readlines("sample.txt") # IO.readlines 类似 puts "第 0 行: #{lines_array[0].chomp if lines_array[0]}" puts "第 1 行: #{lines_array[1].chomp if lines_array[1]}"rescue Errno::ENOENT puts "文件未找到。"endIO.foreach 和 File.foreach 方法:
Section titled “IO.foreach 和 File.foreach 方法:”遍历文件的每一行,并将其传递给一个块。与 readlines 相比,它逐行处理,内存效率更高,适用于大文件。
#!/usr/bin/env ruby# frozen_string_literal: true
begin File.foreach("sample.txt") do |line| puts "正在处理行: #{line.chomp}" endrescue Errno::ENOENT puts "文件未找到。"end其他常见的读取方法:File.read(filename) 将整个文件内容读取为一个字符串。file.read(length) 读取 length 个字节。
重命名和删除文件
Section titled “重命名和删除文件”File.rename(old_name, new_name) 重命名文件。
File.delete(filename) 或 File.unlink(filename) 删除文件。
#!/usr/bin/env ruby# Create a file to work withFile.write("original.txt", "Some content.")
# Rename the fileif File.exist?("original.txt") File.rename("original.txt", "renamed.txt") puts "original.txt 已重命名为 renamed.txt"end
# Delete the fileif File.exist?("renamed.txt") File.delete("renamed.txt") puts "renamed.txt 已删除"end文件模式和所有权(权限)
Section titled “文件模式和所有权(权限)”使用 File.chmod(mode, filename, ...) 更改一个或多个文件的权限(模式)。mode 是一个八进制数。
#!/usr/bin/env rubyFile.write("script.sh", "#!/bin/bash\necho Hello")# 使其对所有者可执行,对所有者/组/其他用户可读File.chmod(0755, "script.sh")puts "script.sh 的权限已更改。"# File.delete("script.sh") # 清理常见的八进制权限掩码:
| 掩码 | 描述(权限) |
|---|---|
| 0700 | rwx------(所有者:读、写、执行) |
| 0600 | rw-------(所有者:读、写) |
| 0755 | rwxr-xr-x(所有者:rwx;组:rx;其他用户:rx)- 可执行文件/目录常用 |
| 0644 | rw-r—r—(所有者:rw;组:r;其他用户:r)- 普通文件常用 |
文件查询(判断方法)
Section titled “文件查询(判断方法)”Ruby 提供了许多查询文件属性的方法(通常以 ? 结尾):
#!/usr/bin/env ruby# frozen_string_literal: truefilename = "sample.txt"File.write(filename, "Test content for inquiries.") unless File.exist?(filename)
puts "文件 '#{filename}' 是否存在? #{File.exist?(filename)}" # => trueputs "它是一个文件吗? #{File.file?(filename)}" # => trueputs "它是一个目录吗? #{File.directory?(filename)}" # => falseputs "它可读吗? #{File.readable?(filename)}" # => true (通常)puts "它可写吗? #{File.writable?(filename)}" # => true (通常)puts "它可执行吗? #{File.executable?(filename)}" # => false (对于文本文件通常)puts "它大小为零吗? #{File.zero?(filename)}" # => false (如果有内容)puts "大小: #{File.size(filename)} 字节" # => (内容大小)puts "大小(如果为零则为 nil): #{File.size?(filename)} 字节" # => (内容大小,如果为零则为 nil)puts "文件类型: #{File.ftype(filename)}" # => "file"puts "创建时间: #{File.ctime(filename)}"puts "修改时间: #{File.mtime(filename)}"puts "最后访问时间: #{File.atime(filename)}"
# File.delete(filename) # 清理ftype 方法可以返回:file、directory、characterSpecial、blockSpecial、fifo、link、socket 或 unknown。
Ruby 中的目录
Section titled “Ruby 中的目录”Dir 类用于目录操作。
导航和列出目录
Section titled “导航和列出目录”Dir.chdir(path):更改当前工作目录。
Dir.pwd:返回当前工作目录路径。
Dir.entries(path):返回指定路径中所有条目(文件和目录,包括 . 和 ..)的数组。
Dir.foreach(path) { |entry| ... }:遍历条目。
Dir.glob(pattern) 或 Dir[pattern]:返回与模式匹配的文件名数组(通配符如 *、?、[])。
#!/usr/bin/env ruby# frozen_string_literal: true
puts "当前目录: #{Dir.pwd}"
# List entries in current directory (first 5 for brevity)puts "\n'.' 中的条目:"Dir.entries(".").first(5).each { |entry| puts " #{entry}" }
puts "\n'.' 中的 Ruby 文件:"Dir.glob("*.rb").each { |file| puts " #{file}" }# Or: Dir["*.rb"].each { |file| puts " #{file}" }创建和删除目录
Section titled “创建和删除目录”Dir.mkdir(path, mode=0777):创建目录。mode 指定权限。
Dir.delete(path) 或 Dir.rmdir(path) 或 Dir.unlink(path):删除空目录。
#!/usr/bin/env ruby# frozen_string_literal: true
dir_name = "mynewdir"
begin unless Dir.exist?(dir_name) Dir.mkdir(dir_name, 0755) puts "目录 '#{dir_name}' 已创建。" else puts "目录 '#{dir_name}' 已存在。" end
# 对目录进行一些操作 ...
if Dir.exist?(dir_name) Dir.delete(dir_name) puts "目录 '#{dir_name}' 已删除。" endrescue SystemCallError => e puts "目录操作失败: #{e.message}"end临时文件和目录
Section titled “临时文件和目录”对于临时文件,Ruby 的标准库 tmpdir 和 tempfile 很有用。
#!/usr/bin/env ruby# frozen_string_literal: true
require 'tmpdir' # 用于 Dir.tmpdirrequire 'tempfile' # 用于 Tempfile 类
# Using Dir.tmpdir (不太常用于直接文件创建)temp_dir_path = Dir.tmpdircustom_temp_filename = File.join(temp_dir_path, "my_app_temp_#{Process.pid}.dat")puts "自定义临时文件可能位于: #{custom_temp_filename}"# 如果直接使用此方法,需要手动创建和删除。
# Using Tempfile (推荐用于临时文件)begin temp_file = Tempfile.new('app_data_prefix') # 创建一个具有唯一名称的临时文件 temp_file.puts "This is some temporary data." temp_file.puts "当对象终结或关闭时,它将自动删除。"
puts "Tempfile 路径: #{temp_file.path}" temp_file.rewind # 返回开头以便读取 puts "Tempfile 内容: #{temp_file.read.chomp}"
ensure # Tempfile 在垃圾回收或显式关闭和解除链接时自行处理删除 temp_file.close # 关闭文件 temp_file.unlink # 从文件系统删除文件(可选,关闭通常会完成此操作) puts "Tempfile 已关闭并解除链接。"end文件和目录的内置函数
Section titled “文件和目录的内置函数”Ruby 的 File 和 Dir 类,以及 FileUtils(一个标准库模块,需要 require 'fileutils')中的方法,提供了丰富的 API,用于所有常见的文件和目录操作。请查阅官方 Ruby 文档以获取完整的方法列表及其选项。