File I/O
## Learning Objectives
- Open and close filehandles
- Read from files
- Write to files
- Use directory operations
- Work with file tests
- Handle binary data
## Filehandles
### Opening Files
```perl
use strict;
use warnings;
# Read from file
open my $fh, "<", "input.txt" or die "Cannot open: $!";
# Write to file (overwrite)
open my $fh, ">", "output.txt" or die "Cannot open: $!";
# Append to file
open my $fh, ">>", "log.txt" or die "Cannot open: $!";
# Read/Write (read + write, truncate)
open my $fh, "+>", "temp.txt" or die "Cannot open: $!";
# Read/Write (read + write, no truncate)
open my $fh, "+<", "temp.txt" or die "Cannot open: $!";
```
### Three-Argument Open
```perl
# Modern way (recommended)
open my $fh, "<", "filename.txt" or die "Cannot open: $!";
# With encoding
open my $fh, "<:encoding(UTF-8)", "file.txt" or die "Cannot open: $!";
# Raw binary
open my $fh, "<:raw", "binary.dat" or die "Cannot open: $!";
```
### Closing Files
```perl
close $fh or die "Cannot close: $!";
```
## Reading from Files
### Line-by-Line Reading
```perl
use strict;
use warnings;
open my $fh, "<", "input.txt" or die "Cannot open: $!";
while (my $line = <$fh>) {
chomp $line;
print "Read: $line\n";
}
close $fh;
```
### Reading into Array
```perl
open my $fh, "<", "input.txt" or die "Cannot open: $!";
my @lines = <$fh>;
close $fh;
# More efficient - slurp entire file
open my $fh, "<", "input.txt" or die "Cannot open: $!";
my $content = do { local $/; <$fh> }; # Slurp mode
close $fh;
```
### Read All Lines
```perl
# Using File::Slurp (CPAN module)
use File::Slurp qw(read_file write_file);
my @lines = read_file("file.txt");
my $content = read_file("file.txt");
```
## Writing to Files
### Print to Filehandle
```perl
use strict;
use warnings;
open my $fh, ">", "output.txt" or die "Cannot open: $!";
print $fh "Hello, World!\n";
print $fh "Line 2\n";
close $fh;
```
### printf to File
```perl
open my $fh, ">", "data.txt" or die "Cannot open: $!";
printf $fh "Name: %-10s Age: %3d\n", "Alice", 30;
printf $fh "Name: %-10s Age: %3d\n", "Bob", 25;
close $fh;
```
### write (Formatted)
```perl
use strict;
use warnings;
format STUDENT =
@<<<<<<<<<<< @>> @####.##
Name: Age: GPA
~~ ~~ ~~~~~
.
# Write using format
open my $fh, ">", "students.txt" or die "Cannot open: $!";
select $fh;
write;
select STDOUT;
close $fh;
```
## Standard Filehandles
### STDIN, STDOUT, STDERR
```perl
use strict;
use warnings;
# Read from STDIN
print "Enter your name: ";
my $name = ;
chomp $name;
# Print to STDOUT
print STDOUT "Hello, $name!\n";
# Print to STDERR
print STDERR "Error message\n";
```
### Redirecting Output
```perl
# Redirect STDERR to STDOUT
print STDERR "Error\n"; # Goes to stderr
# Combined
open my $log, ">>", "log.txt" or die "Cannot open: $!";
print $log "Message\n"; # Appends to log
close $log;
```
## File Tests
### Test Operators
```perl
use strict;
use warnings;
use -e File::Spec;
my $file = "test.txt";
-e $file; # Exists?
-r $file; # Readable?
-w $file; # Writable?
-x $file; # Executable?
-f $file; # Regular file?
-d $file; # Directory?
-l $file; # Symbolic link?
-s $file; # Size in bytes (returns size or undef)
-z $file; # Empty file?
-T $file; # Text file?
-B $file; # Binary file?
```
### File Test Examples
```perl
use strict;
use warnings;
my $file = "data.txt";
if (-e $file) {
print "File exists\n";
if (-r $file && -w $file) {
print "File is readable and writable\n";
}
if (-s $file > 1024) {
print "File is larger than 1KB\n";
}
} else {
print "File does not exist\n";
}
```
### Stacked Tests
```perl
my $file = "test.txt";
if (-r -w -x $file) {
print "Full permissions\n";
}
if (-o $file) { # Owned by current user
print "You own this file\n";
}
```
## Directory Operations
### Reading Directories
```perl
use strict;
use warnings;
opendir my $dh, "." or die "Cannot open dir: $!";
while (my $entry = readdir $dh) {
next if $entry =~ /^\./; # Skip hidden files
print "$entry\n";
}
closedir $dh;
```
### Globbing
```perl
use strict;
use warnings;
# All files matching pattern
my @pl_files = glob "*.pl";
my @pl_files = <*.pl>;
# All files recursively (Perl 5.10+)
use File::Glob qw(bsd_glob);
my @all = bsd_glob("**/*", GLOB_NOCHECK);
```
### Making Directories
```perl
use strict;
use warnings;
mkdir "newdir", 0755 or die "Cannot create: $!";
# Recursive mkdir
use File::Path qw(make_path);
make_path("path/to/deep/dir");
# Remove directory (must be empty)
rmdir "emptydir" or die "Cannot remove: $!";
```
### Removing Files
```perl
use strict;
use warnings;
unlink "file_to_delete.txt" or die "Cannot delete: $!";
# Remove multiple
unlink "a.txt", "b.txt", "c.txt";
# Remove with check
unlink "old.txt" if -e "old.txt";
```
## Path Manipulation
### File::Spec
```perl
use strict;
use warnings;
use File::Spec;
my $path = File::Spec->catfile("dir", "subdir", "file.txt");
# Cross-platform path building
my $full = File::Spec->catpath("C:", "Users", "test.txt");
```
### Path::Tiny (CPAN)
```perl
use Path::Tiny;
my $path = path("dir/file.txt");
$path->slurp; # Read content
$path->spew("content"); # Write content
$path->exists;
$path->is_file;
$path->is_dir;
$path->parent; # Parent directory
$path->child("sub"); # Child path
```
## Working with File Paths
### Extracting Components
```perl
use strict;
use warnings;
use File::Basename;
my $path = "/home/user/docs/file.txt";
my $filename = fileparse($path); # "file.txt"
my $dirname = dirname($path); # "/home/user/docs"
my $extension = fileparse($path, qr/\.[^.]*/); # ".txt"
```
### Path Information
```perl
use File::Basename;
my $path = "/home/user/docs/file.txt";
my ($name, $dir, $ext) = fileparse($path, qr/\.[^.]*/);
print "Name: $name, Dir: $dir, Ext: $ext\n";
```
## Binary Data
### Reading Binary
```perl
use strict;
use warnings;
open my $fh, "<:raw", "image.png" or die "Cannot open: $!";
binmode $fh; # Important on Windows
my $data;
{
local $/; # Slurp mode
$data = <$fh>;
}
close $fh;
print length($data), " bytes\n";
```
### Writing Binary
```perl
use strict;
use warnings;
open my $fh, ">:raw", "output.bin" or die "Cannot open: $!";
binmode $fh;
print $fh $binary_data;
close $fh;
```
## Temporary Files
### Named Temporary Files
```perl
use strict;
use warnings;
use File::Temp qw(tempfile);
my ($fh, $filename) = tempfile(
"prefixXXXXX", # Template with X's for random chars
DIR => "/tmp",
SUFFIX => ".txt",
);
print $fh "Temporary content\n";
close $fh;
unlink $filename if -e $filename;
```
### Anonymous Temporary File
```perl
use File::Temp qw(tempfile);
my ($fh, $filename) = tempfile();
print $fh "Temp content\n";
close $fh;
unlink $filename;
```
## Error Handling
### Checking Open Success
```perl
use strict;
use warnings;
open my $fh, "<", "nonexistent.txt"
or die "Cannot open file: $!";
# Or with or
open(my $fh, "<", "file.txt") || die "Cannot open: $!";
# Custom error
open my $fh, "<", "file.txt"
or die "Cannot open 'file.txt': $!";
```
### $! Variable
```perl
open my $fh, "<", "file.txt" or do {
warn "Error: $!";
return;
};
```
## Summary
- Use `open` with three arguments for safety
- `<$fh>` reads one line, `<$fh>` in list context reads all
- `print $fh` writes to file
- `close $fh` when done
- File tests: `-e`, `-r`, `-w`, `-f`, `-d`, `-s`
- `opendir`/`readdir` for directories
- `glob` or `` for file globbing
- `mkdir`/`rmdir` for directory operations
- `unlink` to delete files
- Use `binmode` for binary data
- File::Temp for temporary files
Comments
Comments powered by Giscus
To enable comments, add your Giscus embed code here.
Learn more about Giscus →