File I/O
## Learning Objectives
- Read from and write to files
- Work with file paths and directories
- Use File class methods
- Handle file-related exceptions
## File Reading
### Read Entire File
```ruby
content = File.read("example.txt")
puts content
```
### Read Line by Line
```ruby
File.open("example.txt", "r") do |file|
file.each_line do |line|
puts line
end
end
# Or with block shorthand
File.foreach("example.txt") { |line| puts line }
```
### Read with Encoding
```ruby
content = File.read("example.txt", encoding: "UTF-8")
content = File.read("example.txt", encoding: "Windows-1252")
```
## File Writing
### Write to File
```ruby
File.write("output.txt", "Hello, World!")
# Append mode
File.write("output.txt", "More content\n", mode: "a")
```
### Open and Write
```ruby
File.open("output.txt", "w") do |file|
file.puts "Line 1"
file.puts "Line 2"
file.write "No newline"
end
```
## File Modes
| Mode | Description |
|------|-------------|
| `r` | Read only (default) |
| `w` | Write only (truncates) |
| `a` | Append |
| `r+` | Read and write |
| `w+` | Read and write (truncates) |
| `a+` | Read and append |
## File Operations
### Check File Existence
```ruby
File.exist?("example.txt")
File.file?("example.txt")
File.directory?("path")
```
### File Info
```ruby
File.size("example.txt")
File.mtime("example.txt") # Modification time
File.atime("example.txt") # Access time
File.extname("file.txt") # ".txt"
File.basename("/path/file.txt") # "file.txt"
File.dirname("/path/file.txt") # "/path"
```
### Copy, Move, Delete
```ruby
FileUtils.cp("source.txt", "dest.txt")
FileUtils.mv("old.txt", "new.txt")
FileUtils.rm("file.txt")
# Or built-in
File.copy("source.txt", "dest.txt")
File.delete("file.txt")
```
## Directories
### Reading Directory Contents
```ruby
Dir.foreach(".") do |entry|
puts entry unless entry.start_with?(".")
end
# Glob pattern
Dir.glob("*.rb") # All Ruby files
Dir.glob("**/*.rb") # Recursive
Dir.glob("{app,config}/*.rb") # Multiple patterns
```
### Create and Delete Directories
```ruby
Dir.mkdir("new_directory")
Dir.rmdir("empty_directory")
# Recursive create
require 'fileutils'
FileUtils.mkdir_p("a/b/c/d")
```
### Change Directory
```ruby
Dir.chdir("/tmp")
puts Dir.pwd # Current directory
```
## Pathname
```ruby
require 'pathname'
path = Pathname.new("/home/user/docs/report.pdf")
path.basename # "report.pdf"
path.dirname # "/home/user/docs"
path.extname # ".pdf"
path.parent # "/home/user/docs"
path.join("..", "backup", "report.pdf")
path.exist?
path.directory?
path.file?
```
## Working with CSV
```ruby
require 'csv'
# Reading
CSV.foreach("data.csv") do |row|
puts row.join(", ")
end
# Writing
CSV.open("output.csv", "w") do |csv|
csv << ["Name", "Age"]
csv << ["Alice", 30]
csv << ["Bob", 25]
end
# To array
csv_data = CSV.read("data.csv")
```
## Working with JSON
```ruby
require 'json'
# Read JSON
json_string = File.read("data.json")
data = JSON.parse(json_string)
# Write JSON
data = { name: "Alice", age: 30 }
File.write("data.json", JSON.generate(data))
# Pretty print
File.write("data.json", JSON.pretty_generate(data))
```
## Working with YAML
```ruby
require 'yaml'
# Read YAML
data = YAML.load_file("config.yml")
# Write YAML
File.write("config.yml", YAML.dump(data))
```
## Tempfile
```ruby
require 'tempfile'
file = Tempfile.new("myapp")
file.write("Temporary data")
file.rewind
puts file.read
file.close
file.unlink # Delete
# Block form - auto cleans up
Tempfile.create("myapp") do |f|
f.write("Temporary data")
puts f.read
end
```
## File Locking
```ruby
File.open("shared.txt", "w") do |f|
f.flock(File::LOCK_EX) # Exclusive lock
f.write("Data")
f.flock(File::LOCK_UN) # Unlock
end
# Shared lock for reading
File.open("shared.txt", "r") do |f|
f.flock(File::LOCK_SH) # Shared lock
puts f.read
end
```
## Binary Files
```ruby
# Read binary
File.binread("image.png")
# Write binary
File.binwrite("copy.png", File.binread("original.png"))
# With mode
File.open("image.png", "rb") do |f|
data = f.read
end
```
## Error Handling with Files
```ruby
begin
File.open("example.txt", "r") do |file|
content = file.read
end
rescue Errno::ENOENT
puts "File not found"
rescue Errno::EACCES
puts "Permission denied"
rescue => e
puts "Error: #{e.message}"
end
```
## Summary
- `File.read`/`File.write` for simple operations
- `File.open` with block ensures proper closing
- File modes: `r`, `w`, `a`, `r+`, `w+`, `a+`
- `Dir` class for directory operations
- `Pathname` for path manipulation
- `CSV`, `JSON`, `YAML` libraries for structured data
- `Tempfile` for temporary files
- `FileUtils` for common file operations
- Handle `Errno::ENOENT` for missing files
Comments
Comments powered by Giscus
To enable comments, add your Giscus embed code here.
Learn more about Giscus →