Read and write files

Contents
Three-argument open
Read line by line
Write and append
Read it all at once
Encoding layer

Three-argument open

open takes a filehandle, a mode and a file name. Always use the three-argument form: it keeps the file name out of the mode string, so a name that starts with a pipe or a greater-than sign cannot change what open does.

The first examples on this page work on one small file, data.txt. Create it in the directory you run the script from, and save each snippet as demo.pl before you run it:

printf 'ok line\nerror: disk full\nfine\n' > data.txt

open my $fh, "<", "data.txt" or die "cannot open data.txt: $!\n";

The four modes you need are < for reading, > for writing, >> for appending, and +< for read and write. The special variable $! holds the reason the call failed.

Read line by line

In scalar context the readline operator returns one line at a time, including its newline, and undef at the end of the file. That makes it the natural condition of a while loop.

open my $fh, "<", "data.txt" or die "open: $!\n"; while (my $line = <$fh>) { chomp $line; print "$line\n" if $line =~ /error/; } close $fh;

perl demo.pl

error: disk full

Do not write while (my $line = <$fh>) and then test if ($line) instead of the loop condition. A file whose last line is a single zero would stop the loop early, because 0 is false.

Write and append

The greater-than mode truncates the file, so every run starts from an empty file. Two greater-than signs append instead, which is what log writers need.

open my $out, ">", "report.txt" or die "write: $!\n"; print $out "total: 42\n"; close $out or die "close: $!\n";

cat report.txt

total: 42

The file holds the one line the script wrote. Check close as well: a full disk often reports the error there, after print has already returned success. The autodie pragma in lesson 30 turns all of these checks into automatic exceptions.

Read it all at once

Setting the input record separator to undef makes the next read return the whole file. This is fine for small configuration files and dangerous for gigabyte logs.

The demo measures config.ini, so create that file first:

printf '[main]\nport = 8080\n' > config.ini

open my $fh, "<", "config.ini" or die "open: $!\n"; my $all = do { local $/; <$fh> }; close $fh; print length $all, " bytes\n";

perl demo.pl

19 bytes

The local keyword gives the change a scope, so the rest of the program keeps reading lines normally. Without local, every later read would return whole files.

Encoding layer

Perl works on characters, files hold bytes. Without a layer, a UTF-8 file arrives as a string of bytes and length counts bytes instead of characters. Put the layer in the mode string.

The demo prints the length of every line of names.txt, so create that file first:

printf 'Ada\nGrace\n' > names.txt

open my $fh, "<:encoding(UTF-8)", "names.txt" or die "open: $!\n"; while (my $line = <$fh>) { chomp $line; print length $line, "\n"; }

perl demo.pl

3
5

Both names are plain ASCII here, so 3 and 5 are characters and bytes at once. Add an accented name and the two counts separate: without the layer José gives 5 bytes, with it 4 characters.

Add the same layer on output, >:encoding(UTF-8), or the characters are written as raw bytes and the file breaks for everyone else. Lesson 36 shows the one-line way to set this for all filehandles at once.

Next: File tests and metadata

Article author: Arthur Isaev

Related articles
Perl
Perl course: zero to hero in 50 lessons
What is Perl and where it runs
Install Perl and check the version
Your first Perl script
The debugger as a REPL
Scalars and sigils
Numbers
Strings
Interpolation and quoting
Arrays
push, pop, shift and splice
Hashes
keys, values, exists and delete
Scalar and list context
Conditions and comparison
while, for, next and last
foreach and the default variable
Subroutines
Arguments in @_
References
Nested data structures
Regular expressions: match and anchors
Captures and named groups
Substitution with s///
split and join
grep and map
Sort and the Schwartzian transform
Read and write files
File tests and metadata
Directories and paths
die, warn and eval
Modules and Exporter
CPAN and cpanm
Objects with bless
Modern objects with Moo
Testing with Test::More
strict, warnings and diagnostics
Options with Getopt::Long
Environment and %ENV
system, backticks and pipes
One-liners with -n and -p
CSV and TSV processing
JSON with JSON::PP
HTTP clients with HTTP::Tiny
Sockets and IO::Socket
Databases with DBI
Capstone: todo CLI
Capstone: log report
Performance and profiling
Modern Perl tour
Hero roadmap: the whole course on one page
Install Perl on Windows 11
Install Perl on Ubuntu
Install Perl on Rocky Linux
Install Perl on macOS
Install Perl on FreeBSD
Perl in Docker
Banner image

Search this site

Channel @aofeed Chat @aofeedchat

Contacts and cooperation:
I recommend our hosting beget.com
Write to info@aredel.com if you:
1. Want to write an article for our site or translate an article into your native language.
2. Want to place thematically relevant ads on the site.
3. Ads on my site pass maximum censorship. If you see an ad block unsuitable for school-age children, shocking or misleading - please contact us by e-mail
4. Found a mistake, inaccuracy, bug, etc. on the site. ... .......
5. Articles can be shared on social media by clicking a network icon: