Perl File I/O
Perl - File I/O
Section titled “Perl - File I/O”File I/O (Input/Output) in Perl involves associating a filehandle with an external entity (usually a file) and then using Perl’s operators and functions to read from or write to that entity.
A filehandle is an internal Perl name that connects your script to a file or device. Modern Perl uses lexical filehandles (variables storing the filehandle) for better scope control and error handling.
Perl predefines three standard filehandles: STDIN (standard input), STDOUT (standard output), and STDERR (standard error).
Opening and Closing Files
Section titled “Opening and Closing Files”The primary function for opening files is open(). For lower-level control, sysopen() can be used.
Modern open() Syntax (Three-Argument Form):
open(my $fh, '<', $filename) or die "Cannot open $filename for reading: $!";open(my $fh, '>', $filename) or die "Cannot open $filename for writing: $!";open(my $fh, '>>', $filename) or die "Cannot open $filename for appending: $!";$fh is a lexical filehandle. $filename is the path to the file. The second argument is the mode. $! contains the system error message if open() fails.
It’s highly recommended to add use strict; and use warnings; at the beginning of your scripts for robust error checking.
Open Function Modes
Section titled “Open Function Modes”Here’s a table of common modes for the three-argument open():
| Mode String | Description |
|---|---|
| ’<‘ | Open for reading (read-only). File must exist. |
| ’>‘ | Open for writing. Creates file if it doesn’t exist, truncates (empties) if it does. |
| ’>>‘ | Open for appending. Creates file if it doesn’t exist. Writes will be added to the end. |
| ’+<‘ | Open for reading and writing. File must exist. |
| ’+>‘ | Open for reading and writing. Creates file if it doesn’t exist, truncates if it does. |
| ’+>>‘ | Open for reading and appending. Creates file if it doesn’t exist. Writes will be added to the end. |
For handling character encodings (e.g., UTF-8), you can add layers to the mode:
open(my $fh, '<:encoding(UTF-8)', $filename) or die "...: $!";open(my $fh, '>:encoding(UTF-8)', $filename) or die "...: $!";Example: Reading from a file
#!/usr/bin/perluse strict;use warnings;
my $filename = 'file.txt';open(my $fh, '<', $filename) or die "Could not open file '$filename': $!";
print "Reading from $filename:\n";while (my $row = <$fh>) { chomp $row; # Remove newline character print "Line: $row\n";}close($fh);Example: Writing to a file (truncates if exists)
#!/usr/bin/perluse strict;use warnings;
my $filename = 'output.txt';open(my $fh, '>', $filename) or die "Could not open file '$filename' for writing: $!";
print $fh "Hello, file!\n";print $fh "This is a new line.\n";
close($fh);print "Data written to $filename\n";Sysopen Function
Section titled “Sysopen Function”sysopen() provides lower-level access to the system’s open() call. It requires the Fcntl module for constants.
sysopen(my $fh, $filename, $flags) or die "sysopen $filename: $!";sysopen(my $fh, $filename, $flags, $perms) or die "sysopen $filename: $!";$flags are constants like O_RDONLY, O_WRONLY, O_RDWR, O_CREAT, O_TRUNC, O_APPEND (imported from Fcntl). $perms specifies permissions if the file is created (e.g., 0666).
Example using sysopen:
#!/usr/bin/perluse strict;use warnings;use Fcntl qw(:DEFAULT O_CREAT O_TRUNC); # Import constants
my $filename = 'sysopened.txt';my $permissions = 0644;sysopen(my $fh, $filename, O_WRONLY | O_CREAT | O_TRUNC, $permissions) or die "Cannot sysopen $filename: $!";
print $fh "Written via sysopen.\n";close($fh);print "Data written to $filename using sysopen.\n";Common Fcntl constants for sysopen mode:
| Constant | Description |
|---|---|
| O_RDONLY | Read Only |
| O_WRONLY | Write Only |
| O_RDWR | Read and Write |
| O_CREAT | Create the file if it doesn’t exist |
| O_APPEND | Append to the file |
| O_TRUNC | Truncate the file (empty it) |
| O_EXCL | Used with O_CREAT, fails if file already exists |
| O_NONBLOCK | Non-blocking I/O |
Close Function
Section titled “Close Function”The close() function flushes buffers and disassociates the filehandle from the file.
close($fh) or die "Could not close filehandle: $!";It’s good practice to check the return value of close(), especially for output filehandles, as errors during flushing can occur.
Reading and Writing Files
Section titled “Reading and Writing Files”Once a filehandle is open, you can read from or write to it.
The Diamond Operator <$fh>
Section titled “The Diamond Operator <$fh>”The primary way to read from a filehandle is the diamond operator <$fh>. In scalar context, it reads one line. In list context, it reads all remaining lines.
#!/usr/bin/perluse strict;use warnings;
# Assuming 'input.txt' exists and has contentmy $filename_in = 'input.txt';open(my $in_fh, '<', $filename_in) or die "Cannot open $filename_in: $!";
# Scalar context: read one linemy $first_line = <$in_fh>;chomp $first_line if defined $first_line;print "First line: $first_line\n";
# List context: read all remaining lines into an arraymy @remaining_lines = <$in_fh>;close($in_fh);
print "Remaining lines:\n";for my $line (@remaining_lines) { chomp $line; print "- $line\n";}<STDIN> reads a line from standard input.
getc Function
Section titled “getc Function”getc($fh) reads a single character from the filehandle. Returns undef on error or end-of-file.
read Function
Section titled “read Function”read($fh, my $buffer, $length, $offset) reads $length bytes into $buffer. If $offset is specified, it reads into $buffer starting at that offset. Useful for binary data.
print Function
Section titled “print Function”print $fh LIST writes the items in LIST to the specified filehandle. If $fh is omitted, prints to STDOUT (or the currently selected default output handle).
#!/usr/bin/perluse strict;use warnings;
my $filename_out = 'greetings.txt';open(my $out_fh, '>', $filename_out) or die "Cannot open $filename_out: $!";
print $out_fh "Hello, world!\n"; # Write to fileprint "Message written to $filename_out\n"; # Write to STDOUT
close($out_fh);Copying Files
Section titled “Copying Files”A common task is copying content from one file to another.
#!/usr/bin/perluse strict;use warnings;
my $source_file = 'source.txt'; # Assume this file existsmy $dest_file = 'destination.txt';
open(my $source_fh, '<', $source_file) or die "Cannot open source file '$source_file': $!";open(my $dest_fh, '>', $dest_file) or die "Cannot open destination file '$dest_file': $!";
# Copy line by linewhile (my $line = <$source_fh>) { print $dest_fh $line;}
close($source_fh);close($dest_fh) or die "Error closing destination file '$dest_file': $!";
print "File '$source_file' copied to '$dest_file'\n";For binary files or larger files, consider reading in chunks using read() for efficiency.
Renaming a file
Section titled “Renaming a file”The rename() function renames a file.
#!/usr/bin/perluse strict;use warnings;
my $old_name = 'oldfile.txt';my $new_name = 'newfile.txt';
# Create a dummy old file for the exampleopen(my $fh, '>', $old_name) or die "Could not create $old_name: $!";print $fh "This is the old file.\n";close($fh);
if (rename($old_name, $new_name)) { print "File '$old_name' renamed to '$new_name' successfully.\n";} else { warn "Could not rename '$old_name' to '$new_name': $!";}Deleting an Existing File
Section titled “Deleting an Existing File”The unlink() function deletes one or more files.
#!/usr/bin/perluse strict;use warnings;
my $file_to_delete = 'tempfile.txt';
# Create a dummy file for the exampleopen(my $fh, '>', $file_to_delete) or die "Could not create $file_to_delete: $!";print $fh "This file will be deleted.\n";close($fh);
if (unlink($file_to_delete)) { print "File '$file_to_delete' deleted successfully.\n";} else { warn "Could not delete '$file_to_delete': $!";}Positioning inside a File
Section titled “Positioning inside a File”tell() returns the current position (in bytes) of the file pointer. seek() moves the file pointer to a specific position.
tell Function
Section titled “tell Function”my $current_position = tell($fh);seek Function
Section titled “seek Function”seek($fh, $position, $whence);$position is the offset. $whence determines how $position is interpreted:
- 0: Seek from the beginning of the file (SEEK_SET).
- 1: Seek from the current position (SEEK_CUR).
- 2: Seek from the end of the file (SEEK_END).
These constants (SEEK_SET, SEEK_CUR, SEEK_END) can be imported from the Fcntl or IO::Seekable modules. Using the numeric values 0, 1, 2 is also common.
# Example: Seek to byte 10 from the beginningseek($fh, 10, 0) or die "Seek failed: $!";File Information (File Test Operators)
Section titled “File Information (File Test Operators)”Perl provides file test operators (e.g., -e, -f, -d) to check various attributes of a file or directory.
#!/usr/bin/perluse strict;use warnings;
my $file = 'example.txt'; # Or any file/directory path
# Create a dummy file for testingopen (my $fh, '>', $file) or die "Could not create $file: $!";print $fh "Some content\n";close ($fh);
if (-e $file) { print "'$file' exists.\n"; print "'$file' is a plain file.\n" if (-f _); # _ refers to the last stat'd filehandle print "'$file' is a directory.\n" if (-d _); print "'$file' is readable.\n" if (-r _); print "'$file' is writable.\n" if (-w _); print "'$file' is executable.\n" if (-x _); print "'$file' size is: ", -s _, " bytes.\n" if (-s _); print "'$file' is a text file.\n" if (-T _); print "'$file' is a binary file.\n" if (-B _);} else { print "'$file' does not exist.\n";}
unlink $file; # Clean up dummy fileCommon File Test Operators:
| Operator | Definition |
|---|---|
| -e | File or directory exists. |
| -f | Is a plain file. |
| -d | Is a directory. |
| -r | Is readable by effective UID/GID. |
| -w | Is writable by effective UID/GID. |
| -x | Is executable by effective UID/GID. |
| -s | File size in bytes (returns size, or undef if file doesn’t exist). |
| -z | File has zero size (is empty). |
| -l | Is a symbolic link. |
| -T | File looks like a text file. |
| -B | File looks like a binary file. |
| -M | Age of file (modification time - script start time) in days. |
| -A | Age of file (access time - script start time) in days. |
| -C | Age of file (inode change time - script start time) in days. |
For more advanced file and directory manipulation, consider CPAN modules like Path::Tiny or File::Spec.