Encode::Unicode(3perl)
πΈ NAME πΈ
Encode::Unicode β Various Unicode Transformation Formats
that's it, that's the whole vibe. she does Unicode Transformation Formats and she does them well. π
β¨ SYNOPSIS β¨
use Encode qw/encode decode/;
$ucs2 = encode("UCS-2BE", $utf8);
$utf8 = decode("UCS-2BE", $ucs2);
like yes bestie, encode in, decode out, that's the whole friendship. π«Ά
π¦ ABSTRACT π¦
okay so here's the deal: this module implements all the Character Encoding Schemes of Unicode that are officially documented by the Unicode Consortium. the one glaring exception is UTF-8, obviously, and that's because UTF-8 is a native format in perl. she was born here. she doesn't need an implementation. periodt. π
and <http://www.unicode.org/glossary/> straight up says, and I quote:
Character Encoding Scheme A character encoding form plus byte serialization. There are Seven character encoding schemes in Unicode: UTF-8, UTF-16, UTF-16BE, UTF-16LE, UTF-32 (UCS-4), UTF-32BE (UCS-4BE) and UTF-32LE (UCS-4LE), and UTF-7. Since UTF-7 is a 7-bit (re)encoded version of UTF-16BE, It is not part of Unicode's Character Encoding Scheme. It is separately implemented in Encode::Unicode::UTF7. For details see Encode::Unicode::UTF7.
so yeah, UTF-7 is a whole separate girl β she lives in Encode::Unicode::UTF7, not here. go check her out if that's your thing. π¦
π₯ Quick Reference π₯
here's the cheat sheet, screenshot it, put it on your wall, whatever:
Decodes from ord(N) Encodes chr(N) to...
octet/char BOM S.P d800-dfff ord > 0xffff \x{1abcd} ==
---------------+-----------------+------------------------------
UCS-2BE 2 N N is bogus Not Available
UCS-2LE 2 N N bogus Not Available
UTF-16 2/4 Y Y is S.P S.P BE/LE
UTF-16BE 2/4 N Y S.P S.P 0xd82a,0xdfcd
UTF-16LE 2/4 N Y S.P S.P 0x2ad8,0xcddf
UTF-32 4 Y - is bogus As is BE/LE
UTF-32BE 4 N - bogus As is 0x0001abcd
UTF-32LE 4 N - bogus As is 0xcdab0100
UTF-8 1-4 - - bogus >= 4 octets \xf0\x9a\af\8d
---------------+-----------------+------------------------------
that's giving β main character table β ngl.
π Size, Endianness, and BOM π
so you can sort every one of these CES into three little boxes, and those boxes are: size of each character, endianness, and Byte Order Mark. three criteria, one glow-up. β¨
π by size π
- UCS-2 is a fixed-length encoding where each character takes 16 bits. she does not support surrogate pairs, she refuses, she's not doing it. when a surrogate pair shows up during
decode(), its place gets filled with\x{FFFD}ifCHECKis0, or the routine croaks ifCHECKis1. same energy for a character whose ord value is bigger than0xFFFFβ filled with\x{FFFD}ifCHECKis0, croaks ifCHECKis1. no in-between, bestie. π - UTF-16 is almost the same as UCS-2 except she actually supports surrogate pairs, and honestly? good for her. when she bumps into a high surrogate (
0xD800-0xDBFF), she goes and fetches the following low surrogate (0xDC00-0xDFFF) and "desurrogate"s them to form a character. bogus surrogates result in death. literally. when\x{10000}or above shows up duringencode(), she "ensurrogate"s them and pushes the surrogate pair straight to the output stream. iconique. π - UTF-32 (also known as UCS-4) is a fixed-length encoding where each character takes 32 bits. and since it's 32-bit, there is no need for surrogate pairs at all. she said no drama, no pairs, we're thriving. π§
π by endianness π
fun history lesson: the first goal of Unicode β and yes, it's the now failed goal, we don't talk about it β was to map all character repertoires into a single fixed-length integer so programmers would be happy. π since each character is either a short or a long in C, you've gotta pay attention to the endianness of each platform when you're passing data between them. this is the part where it gets real.
anything marked BE is Big Endian (aka network byte order) and LE is Little Endian (aka VAX byte order). and for anything that isn't marked BE or LE? a character called a Byte Order Mark (BOM) that tells you the endianness gets prepended to the string. she announces herself. πββοΈ
CAVEAT: though BOM in utf8 (\xEF\xBB\xBF) is valid, it is meaningless, and as of this writing the Encode suite just leaves it as is (\x{FeFF}). like okay girl, do your thing I guess. π
BOM as integer when fetched in network byte order:
16 32 bits/char
-------------------------
BE 0xFeFF 0x0000FeFF
LE 0xFFFe 0xFFFe0000
-------------------------
and this module handles the BOM like this, bestie, take notes:
- when BE or LE is explicitly stated as the name of the encoding, the BOM is simply treated as a normal character β that's ZERO WIDTH NO-BREAK SPACE to you and me.
- when BE or LE is omitted during
decode(), it checks if a BOM is sitting at the beginning of the string; if one is found, the endianness gets set to whatever the BOM says. she listens. π«Ά - Default Byte Order β when no BOM is found, Encode 2.76 and below croaked. but since Encode 2.77, it falls back to BE, accordingly to RFC2781 and the Unicode Standard version 8.0. growth! character development! π±
- when BE or LE is omitted during
encode(), it returns a BE-encoded string with a BOM prepended. so when you want to encode a whole text file, make sure youencode()the whole text at once β not line by line, or each line, and not file, will have a BOM prepended. you've been warned, do not do the thing. π - and
"UCS-2"is the exception to all of this. unlike the others, this one is an alias of UCS-2BE. UCS-2 is already registered by IANA and others that way, so. rules are rules. π
π§ Surrogate Pairs π§
to say the least, surrogate pairs were the biggest mistake of the Unicode Consortium. π but according to the late Douglas Adams in The Hitchhiker's Guide to the Galaxy Trilogy, "In the beginning the Universe was created. This has made a lot of people very angry and been widely regarded as a bad move". their mistake was not of this magnitude so let's forgive them. ποΈ
(I don't dare make any comparison with Unicode Consortium and the Vogons here ;) or, comparing Encode to Babel Fish is completely appropriate β if you can only stick this into your ear :)
so anyway, surrogate pairs were born when the Unicode Consortium finally admitted that 16 bits were not big enough to hold all the world's character repertoires. but they'd already made UCS-2 16-bit. what do we do?? π€
back then, the range 0xD800-0xDFFF was not allocated. so: split that range in half, use the first half to represent the "upper half of a character" and the second half to represent the "lower half of a character". that way you can represent 1024 * 1024 = 1048576 more characters. now we can store character ranges up to \x{10ffff} even with 16-bit encodings. that pair of half-characters is now called a surrogate pair, and UTF-16 is the name of the encoding that embraces them. she said "I'll take them, they're mine now". π₯Ή
here's the formula to ensurrogate a Unicode character \x{10000} and above:
$hi = ($uni - 0x10000) / 0x400 + 0xD800;
$lo = ($uni - 0x10000) % 0x400 + 0xDC00;
and to desurrogate:
$uni = 0x10000 + ($hi - 0xD800) * 0x400 + ($lo - 0xDC00);
math girlies rise. πβ¨
note this move has made\x{D800}-\x{DFFF}into a forbidden zone β but perl does not prohibit the use of characters within this range. to perl, every one of\x{0000_0000}up to\x{ffff_ffff}(*) is just a character. she doesn't judge.
(*) or \x{ffff_ffff_ffff_ffff} if your perl is compiled with 64-bit integer support! look at her go π₯
π Error Checking π
unlike most encodings that accept various ways to handle errors, Unicode encodings simply croaks. that's it. no options, no leniency, no "let's talk about it". she's not interested. π
% perl -MEncode -e'$_ = "\xfe\xff\xd8\xd9\xda\xdb\0\n"' \
-e'Encode::from_to($_, "utf16","shift_jis", 0); print'
UTF-16:Malformed LO surrogate d8d9 at /path/to/Encode.pm line 184.
% perl -MEncode -e'$a = "BOM missing"' \
-e' Encode::from_to($a, "utf16", "shift_jis", 0); print'
UTF-16:Unrecognised BOM 424f at /path/to/Encode.pm line 184.
see? croaked. out loud. in front of everyone. π
unlike other encodings where mappings are not one-to-one against Unicode, UTFs are supposed to map 100% against one another. so Encode is more strict on UTFs.
consider that "division by zero" of Encode :) she said be normal or be nothing. πβ¨
β SEE ALSO β
EncodeEncode::Unicode::UTF7- <https://www.unicode.org/glossary/>
- <https://www.unicode.org/faq/utf_bom.html>
- RFC 2781 <http://www.ietf.org/rfc/rfc2781.txt>
- The whole Unicode standard <https://www.unicode.org/standard/standard.html>
- Ch. 6 pp. 275 of "Programming Perl (3rd Edition)" by Tom Christiansen, brian d foy & Larry Wall; O'Reilly & Associates; ISBN 978-0-596-00492-7
okay that's the whole page bestie, you're officially educated π this one's brought to you by perl v5.44.0, dated 2026-10-17 β go forth and decode() responsibly, ily, mwah πβ¨ππ«Ά
π¦ 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