PerlIO(3perl)
โจ PerlIO โ the vibe โจ
okay bestie, welcome to PerlIO ๐ this is part of the Perl Programmers Reference Guide, and honestly it's the on-demand loader for PerlIO layers AND the root of the whole PerlIO::* name space. no cap. let's get into it ๐ซถ
๐ธ SYNOPSIS ๐ธ
watch me cook ๐งโ๐ณ
# support platform-native and CRLF text files
open(my $fh, "<:crlf", "my.txt") or die "open failed: $!";
# append UTF-8 encoded text
open(my $fh, ">>:encoding(UTF-8)", "some.log")
or die "open failed: $!";
# portably open a binary file for reading
open(my $fh, "<", "his.jpg") or die "open failed: $!";
binmode($fh) or die "binmode failed: $!";
Shell:
PERLIO=:perlio perl ....
๐ DESCRIPTION ๐
so here's the tea โ whenever an undefined layer foo shows up in an open or binmode layer spec, the C code does the equivalent of:
use PerlIO 'foo';
then the Perl code in PerlIO.pm is like "say less" and tries to find a layer by doing:
require PerlIO::foo;
otherwise bestie, the PerlIO package is literally just a placeholder for extra PerlIO-related functions. it's giving home base ๐
๐ Layers ๐
generally speaking (iykyk), PerlIO layers โ which used to sometimes get called "disciplines" back in the day โ are an ordered stack applied to a filehandle. you specify them as a space- or colon-separated list, and convention says you write a leading colon. ๐ฆ
each layer does some operation on any input or output, except when it gets bypassed, like with sysread or syswrite. read operations go through the stack in the order they were set (left to right), and write operations go in the reverse order. periodt.
there are also layers that really just set flags on lower layers, or layers that modify the current stack but don't persist on the stack themselves โ these are referred to as pseudo-layers. iconic behavior honestly โจ
when you open a handle, it gets opened with any layers specified explicitly in the open() call (or the platform defaults, if you specify it as a colon with no following layers).
if layers are not explicitly specified, the handle gets opened with the layers specified by the ${^OPEN} variable (which is usually set by using the open pragma for a lexical scope, or the -C command-line switch or the PERL_UNICODE environment variable for the main program scope).
and if layers aren't specified in the open() call or the ${^OPEN} variable, the handle gets opened with the default layer stack configured for that architecture โ go peep "Defaults and how to override them" for that one. ๐
some layers will automatically insert the required lower level layers if they're not there. for example, :perlio will insert :unix below itself for low level IO, and :encoding will insert the platform defaults for buffered IO. so helpful fr fr ๐ซถ
the binmode function can be called on an opened handle to push additional layers onto the stack, which may also modify the existing layers. and binmode called with no layers will remove or unset any existing layers that transform the byte stream, making the handle suitable for binary data. chef's kiss ๐
the following layers are currently defined:
:unixโ the lowest level layer, providing basic PerlIO operations in terms of UNIX/POSIX numeric file descriptor calls (open(),read(),write(),lseek(),close()). it's used even on non-Unix architectures, and most other layers operate on top of it. founder behavior ๐งฑ:stdioโ a layer that callsfread,fwriteandfseek/ftelletc. heads up tho: because this is "real" stdio, it will ignore any layers beneath it and go straight to the operating system via the C library as usual. this layer implements both low level IO and buffering, but it's rarely used on modern architectures. kinda vintage ngl ๐ต:perlioโ a from-scratch implementation of buffering for PerlIO. it provides fast access to the buffer forsv_gets, which implements Perl's readline/<>, and in general it attempts to minimize data copying.:perliowill insert a:unixlayer below itself to do low level IO. efficient queen ๐:crlfโ a layer that implements DOS/Windows like CRLF line endings. on read it converts pairs of CR,LF to a single"\n"newline character. on write it converts each"\n"to a CR,LF pair. note that this layer will silently refuse to be pushed on top of itself. ๐
it currently does not mimic MS-DOS as far as treating Control-Z as an end-of-file marker.
on DOS/Windows like architectures where this layer is part of the defaults, it also acts like the :perlio layer, and removing the CRLF translation (such as with :raw) will only unset the CRLF translation flag. since Perl 5.14, you can also apply another :crlf layer later, like when the CRLF translation must occur after an encoding layer. on other architectures, it's just a mundane CRLF translation layer and can be added and removed normally.
# translate CRLF after encoding on Perl 5.14 or newer
binmode $fh, ":raw:encoding(UTF-16LE):crlf"
or die "binmode failed: $!";
:utf8โ a pseudo-layer that declares the stream accepts Perl's internal upgraded encoding of characters, which is approximately UTF-8 on ASCII machines, but UTF-EBCDIC on EBCDIC machines. this lets any character Perl can represent be read from or written to the stream. โจ
this layer (which actually just sets a flag on the preceding layer, and is implicitly set by any :encoding layer) does not translate or validate byte sequences. instead it indicates that the byte stream will have been arranged by other layers to be provided in Perl's internal upgraded encoding, which Perl code (and correctly written XS code) will interpret as decoded Unicode characters.
โ ๏ธ CAUTION: do not use this layer to translate from UTF-8 bytes, bestie, because invalid UTF-8 or binary data will result in malformed Perl strings. it's unlikely to produce invalid UTF-8 when used for output, though it will instead produce UTF-EBCDIC on EBCDIC systems. the :encoding(UTF-8) layer (the hyphen is significant!!) is preferred, since it will ensure translation between valid UTF-8 bytes and valid Unicode characters. ๐
:bytesโ this is the inverse of the:utf8pseudo-layer. it turns off the flag on the layer below so that data read from it is considered to be Perl's internal downgraded encoding, thus interpreted as the native single-byte encoding of Latin-1 or EBCDIC. likewise on output, Perl will warn if a "wide" character (a codepoint not in the range 0..255) is written to such a stream.
๐ this is very dangerous to push on a handle using an:encodinglayer, because such a layer assumes it's working with Perl's internal upgraded encoding, so you will likely get a mangled result. instead use:rawor:popto remove encoding layers. don't do it. i'm serious. ๐ญ
:rawโ the:rawpseudo-layer is defined as being identical to callingbinmode($fh)โ the stream is made suitable for passing binary data, i.e. each byte is passed as-is. the stream will still be buffered (but this was not always true before Perl 5.14).
in Perl 5.6 and some books, the :raw layer is documented as the inverse of the :crlf layer. that is no longer the case โ other layers which would alter the binary nature of the stream are also disabled. if you want UNIX line endings on a platform that normally does CRLF translation, but still want UTF-8 or encoding defaults, the appropriate thing to do is to add :perlio to the PERLIO environment variable, or open the handle explicitly with that layer, to replace the platform default of :crlf. ๐ฑ
the implementation of :raw is as a pseudo-layer which, when "pushed", pops itself and then any layers which would modify the binary data stream. (undoing :utf8 and :crlf may be implemented by clearing flags rather than popping layers, but that's an implementation detail. we don't gatekeep.)
as a consequence of the fact that :raw normally pops layers, it usually only makes sense to have it as the only or first element in a layer specification. when used as the first element it provides a known base on which to build, e.g.
open(my $fh,">:raw:encoding(UTF-8)",...)
or die "open failed: $!";
will construct a "binary" stream regardless of the platform defaults, but then enable UTF-8 translation. slay โจ
:popโ a pseudo-layer that removes the top-most layer. it gives Perl code a way to manipulate the layer stack. note that:poponly works on real layers and will not undo the effects of pseudo-layers or flags like:utf8. an example of a possible use might be:
open(my $fh,...) or die "open failed: $!";
...
binmode($fh,":encoding(...)") or die "binmode failed: $!";
# next chunk is encoded
...
binmode($fh,":pop") or die "binmode failed: $!";
# back to un-encoded
a more elegant (and safer) interface is needed. the way that we're all just coping with this ๐ซ
๐ฆ Custom Layers ๐ฆ
plot twist bestie: it is possible to write custom layers in addition to the builtin ones above, both in C/XS and Perl, as a module named PerlIO::<layer name>. some custom layers even come with the Perl distribution. main character energy fr ๐
:encodingโ use:encoding(ENCODING)to transparently do character set and encoding transformations, for example from Shift-JIS to Unicode. note that an:encodingalso enables:utf8. seePerlIO::encodingfor more information. ๐:mmapโ a layer which implements "reading" of files by usingmmap()to make a (whole) file appear in the process's address space, and then using that as PerlIO's "buffer". this may be faster in certain circumstances for large files, and may result in less physical memory use when multiple processes are reading the same file. big file girlies rise ๐ซถ
files which are not mmap()-able revert to behaving like the :perlio layer. writes also behave like the :perlio layer, as mmap() for write needs extra house-keeping (to extend the file) which negates any advantage.
the :mmap layer will not exist if the platform does not support mmap(). see PerlIO::mmap for more information.
:viaโ:via(MODULE)allows a transformation to be applied by an arbitrary Perl module, for example compression / decompression, encryption / decryption. seePerlIO::viafor more information. versatile queen ๐:scalarโ a layer implementing "in memory" files using scalar variables, automatically used in place of the platform defaults for IO when opening such a handle. as such, the scalar is expected to act like a file, only containing or storing bytes. seePerlIO::scalarfor more information. ๐
๐ Alternatives to raw ๐
to get a binary stream, an alternate method is to use:
open(my $fh,"<","whatever") or die "open failed: $!";
binmode($fh) or die "binmode failed: $!";
(part 2 coming up next, bestie โ don't go anywhere) ๐
...which is lowkey the whole point: it stays backward compatible with older Perls that never used PerlIO at all, or where ":raw" was straight-up buggy (which it was, bestie, before Perl 5.14 ๐).
Wanna an unbuffered stream? Then you gotta name an unbuffered layer (like ":unix") right there in the open call:
open(my $fh,"<:unix",$path) or die "open failed: $!";
โจ Defaults and how to override them โจ
Okay so if you're on an MS-DOS-ish platform and it normally does that CRLF โ "\n" translation thing for text files, your default layers are:
:unix:crlf
Otherwise, if Configure worked out how to do "fast" IO using the system's stdio (which, ngl, is not common on modern architectures), your default layers are:
:stdio
And otherwise โ the catch-all โ your defaults are:
:unix:perlio
Sis, the "default stack" is not a one-size-fits-all situation. It depends on your operating system, on your Perl version, and on both the compile-time and runtime configurations of Perl. ๐ฎโ๐จ
You can override the default by setting the environment variable PERLIO to a space- or colon-separated list of layers. But โ and this is the important part โ you cannot use it to set layers that need to load modules, like ":encoding". ๐
โโ๏ธ
This is genuinely such a good trick for seeing the effect of (or bugs in) the various layers, like:
cd .../perl/t
PERLIO=:stdio ./perl harness
PERLIO=:perlio ./perl harness
For the various values of PERLIO see "PERLIO" in perlrun.
Here's the glow-up table summarizing the default layers on UNIX-like and DOS-like platforms, depending on what $ENV{PERLIO} is set to:
PERLIO UNIX-like DOS-like
------ --------- --------
unset / "" :unix:perlio / :stdio [1] :unix:crlf
:stdio :stdio :stdio
:perlio :unix:perlio :unix:perlio
# [1] ":stdio" if Configure found out how to do "fast stdio" (depends
# on the stdio implementation) and in Perl 5.8, else ":unix:perlio"
๐ Querying the layers of filehandles ๐
This one returns the names of the PerlIO layers sitting on a filehandle:
my @layers = PerlIO::get_layers($fh); # Or FH, *FH, "FH".
They come back in the exact order an open() or binmode() call would use them, and with no colons โ clean, no punctuation drama. ๐
By default you get the layers from the input side of the filehandle. Want the output side instead? Pass the optional "output" argument:
my @layers = PerlIO::get_layers($fh, output => 1);
(Usually both sides of a filehandle have identical layers, but with sockets, for example, there can be differences. ๐)
Now listen โ there is no set_layers(). And get_layers() does not hand you back a tied array mirroring the stack, or anything fancy like that. That is not an accident and it is not an oversight, bestie, it's on purpose. The PerlIO layer stack is a bit more complicated than just a stack (see for example the behaviour of ":raw"). The way you're supposed to manipulate the stack is with open() and binmode(). Periodt. ๐
Implementation details follow, please close your eyes. ๐
The arguments to layers are by default returned in parentheses right after the name of the layer. And some layers (like ":utf8") aren't real layers at all โ they're flags on real layers. To get all of these returned separately, use the optional "details" argument:
my @layer_and_args_and_flags = PerlIO::get_layers($fh, details => 1);
The result will be up to three times the number of layers: first element is a name, second element is the arguments (unspecified arguments come back as undef), third element is the flags, fourth element is a name again, and so on and so forth. ๐
You may open your eyes now. ๐ฆ
๐ AUTHOR ๐
Nick Ing-Simmons <nick@ing-simmons.net>
๐ธ SEE ALSO ๐ธ
"binmode" in perlfunc, "open" in perlfunc, perlunicode, perliol, Encode
And that's a wrap, bestie!! ๐ซถ This lil masterpiece is perl v5.44.0, dated 2026-10-17, and it lives at PerlIO(3perl) โ go forth and slay your filehandles. ๐โจ
๐ฆ where this page comes from
- arch rolling: perl 5.44.0-1 ยท Artistic-1.0-Perl AND GPL-1.0-or-later
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms