Perl strings can contain text, but text and the bytes used to store it are not the same thing. Understanding this difference helps you work with characters from different languages.
Consider the word:
my $word = "café";
It contains four characters: c, a, f, and é.
But how many bytes does it occupy?
That depends on the encoding. In UTF-8, the character é occupies two bytes. The complete word therefore occupies five bytes.
An encoding describes how characters are represented as bytes.
Unicode assigns a unique number, called a code point, to each character. For example:
| Character | Unicode code point |
|---|---|
| A | U+0041 |
| é | U+00E9 |
| € | U+20AC |
UTF-8 is a popular way of representing these Unicode characters as bytes.
Perl can work with both text and binary data. A Perl scalar can contain a string of Unicode characters or a sequence of byte values.
use utf8; use feature 'say'; my $text = "café"; my $bytes = "caf\xC3\xA9"; say length($text); # 4 say length($bytes); # 5
The first string contains four Unicode characters. The second contains five byte-valued characters.
The two variables represent the same UTF-8 data, but Perl interprets them differently.
When Perl reads data from a file or another external source, it often receives bytes. To work with these bytes as text, Perl must interpret them using the correct encoding.
This conversion is called decoding.
use Encode qw(decode);
my $bytes = "caf\xC3\xA9";
my $text = decode('UTF-8', $bytes);
say length($text); # 4
The opposite conversion is called encoding. It converts text into bytes, for example when you want to write UTF-8 data to a file.
use Encode qw(encode);
my $text = "café";
my $bytes = encode('UTF-8', $text);
Remember:
You do not always have to use decode() and encode() yourself. Perl can handle these conversions automatically through filehandle layers.
For example, when reading a UTF-8 file:
open my $fh, '<:encoding(UTF-8)', 'input.txt'
or die "Cannot open file: $!";
while (my $line = <$fh>) {
print $line;
}
close $fh;
The :encoding(UTF-8) layer tells Perl that the file contains UTF-8 text. Perl automatically decodes the incoming bytes when reading.
For writing UTF-8 text, use:
open my $fh, '>:encoding(UTF-8)', 'output.txt'
or die "Cannot open file: $!";
print {$fh} "café";
close $fh;
Perl automatically encodes the text as UTF-8 when writing.
There are two ways to decode incoming data:
1. Explicit decoding:
use Encode qw(decode);
my $text = decode('UTF-8', $bytes);
2. Automatic decoding through a filehandle:
open my $fh, '<:encoding(UTF-8)', 'input.txt'
or die $!;
my $text = <$fh>;
Both approaches convert UTF-8 bytes into Perl text. The second is usually more convenient when reading text files.
Remember:
There is no need to call decode() again when the filehandle already performs the conversion.
You may have noticed this statement in Perl programs:
use utf8;
It tells Perl that your source code uses UTF-8. This allows you to write Unicode characters directly in strings:
use utf8; my $word = "café";
However, use utf8 does not configure file input or output. It concerns the Perl source code itself.
Be careful when combining Unicode text and byte strings.
use utf8; my $text = "café"; my $bytes = "caf\xC3\xA9"; my $result = $text . $bytes;
The second variable contains UTF-8 bytes, but Perl does not automatically know that they represent UTF-8 text. An implicit conversion can produce unexpected characters, such as é instead of é.
The solution is to decode the bytes first:
use utf8;
use Encode qw(decode);
my $text = "café";
my $bytes = "caf\xC3\xA9";
my $decoded = decode('UTF-8', $bytes);
my $result = $text . $decoded;
Now both variables contain Unicode text, and they can be combined correctly.
The most important principle is simple:
Work with text as Unicode inside your program. Decode incoming data and encode outgoing data using the appropriate encoding.
Source: chromatic, Modern Perl, Chapter 1, "The Perl Philosophy," section "Unicode and Strings"