Reading, writing, appending#
The three everyday tasks — read an existing file, create one from
scratch, add to the end of one — are three different modes of the
same open call. This page shows each
in the form that actually belongs in new code.
The three-argument form#
open my $fh, MODE, EXPR or die "open: $!";
my $fhis a fresh lexical.openfills it in with a handle reference when it succeeds; on failure it leaves$fhundefined and sets$!.MODEis a short string —"<",">",">>", and a handful of others — that says what you want to do.EXPRis the pathname. It is treated as a plain string: leading or trailing whitespace is preserved, and the string is never reinterpreted as a shell command.
The older two-argument form (open $fh, "<$path") still works,
but it re-parses the string looking for mode characters and for
the “magic” pipe syntax. Do not feed it a filename that came from
a user.
Reading#
my $path = "/etc/hostname";
open my $fh, "<", $path or die "open $path: $!";
while (my $line = <$fh>) {
chomp $line;
# ... work with $line ...
}
close $fh or die "close $path: $!";
Two observations that trip up beginners:
<$fh>callsreadlineunder the hood. In boolean context — as inside thewhilehead — the result is tested for being defined, not truthy. That matters because a file containing the line"0\n"would otherwise stop the loop early.while (<$fh>)is a special-case spelling that Perl rewrites towhile (defined($_ = <$fh>))for you.closecan fail. On a read handle that is rare, but on a write handle it is the moment buffered data is finally flushed, so a closing error is a real error. Check it.
If you want the whole file as one string, slurp it:
open my $fh, "<", $path or die "open $path: $!";
local $/; # undef = slurp mode
my $all = <$fh>;
close $fh or die "close $path: $!";
The local $/ is the idiomatic “for the rest of this scope, turn
off line splitting”. When control leaves the enclosing block, $/
returns to its previous value.
Writing (clobber)#
open my $fh, ">", $path or die "open $path: $!";
print $fh "first line\n";
print $fh "second line\n";
close $fh or die "close $path: $!";
">"creates the file if it does not exist, and truncates it to zero bytes if it does. There is no confirmation step.The filehandle does not need a comma after it in a
printinvocation.print $fh "text"is correct;print $fh, "text"is a different expression that treats$fhas a list element.Buffered writes are held in memory until
close, an explicit flush, or the buffer fills. If your program crashes betweenprintandclose, a writer with pending buffered data loses it. Always pair a writingopenwith a checkedclose.
Appending#
open my $fh, ">>", $path or die "open $path: $!";
print $fh scalar(localtime), " event\n";
close $fh or die "close $path: $!";
">>"creates the file if needed and positions the write cursor at the end.On a POSIX kernel, each
write(2)on an append-mode descriptor is atomic with respect to the file’s end-of-file marker. Two processes appending short lines to the same log therefore interleave line-by-line, not byte-by-byte. Do not rely on that for lines longer thanPIPE_BUFbytes.
Closing as a real step, not a formality#
A failed close on a write handle typically means the kernel
refused to flush — out of space, I/O error, network filesystem
trouble. Treat it exactly like a failed print:
close $fh or die "close $path: $!";
Ignoring it is how “the file looked fine during testing” becomes “production wrote half a log entry and moved on.”
What about read-write?#
"+<" opens a file for both reading and writing, without
truncating. It is a real mode and it works, but it is also the
source of most “my file came out corrupted” bug reports. If you
need random-access reads with in-place overwrites, reach for
sysopen, sysread,
and syswrite so the buffering
layer does not guess at seek positions on your behalf.
For almost every job labelled “edit the file”, the right answer is write a new file, fsync, rename over the old one. That is the pattern atomic editors use.
Next#
With reading, writing, and appending covered, the next question is what the bytes mean. See Encoding and layers.