UTF-16
![]() The first 216Unicode code points. The white stripe near the bottom are the surrogate halves used by UTF-16. | |
Language(s) | International |
---|---|
Standard | Unicode Standard |
Classification | Unicode Transformation Format,variable-width encoding |
Extends | UCS-2 |
Transforms / Encodes | ISO/IEC 10646(Unicode) |
UTF-16(16-bitUnicodeTransformation Format) is acharacter encodingcapable of encoding all 1,112,064 validcode pointsof Unicode (in fact this number of code points is dictated by the design of UTF-16). The encoding isvariable-length,as code points are encoded with one or two 16-bitcode units.UTF-16 arose from an earlier obsolete fixed-width 16-bit encoding now known as "UCS-2" (for 2-byte Universal Character Set),[1][2]once it became clear that more than 216(65,536) code points were needed,[3]including most emoji and importantCJK characterssuch as for personal and place names.[4]
UTF-16 is used by systems such as theMicrosoft WindowsAPI,theJava programming languageandJavaScript/ECMAScript. It is also sometimes used forplain textand word-processing data files on Microsoft Windows. It is used by more modern implementations ofSMS.[5]
UTF-16 is the only encoding (still) allowed on the web that is incompatible withASCII[6][nb 1]and never gained popularity on the web, where it is declared by under 0.004% of web pages.[8]UTF-8,by comparison, accounts for over 98% of all web pages.[9]TheWeb Hypertext Application Technology Working Group (WHATWG)considers UTF-8 "the mandatory encoding for all [text]" and that for security reasons browser applications should not use UTF-16.[10]
History
[edit]In the late 1980s, work began on developing a uniform encoding for a "Universal Character Set" (UCS) that would replace earlier language-specific encodings with one coordinated system. The goal was to include all required characters from most of the world's languages, as well as symbols from technical domains such as science, mathematics, and music. The original idea was to replace the typical 256-character encodings, which required 1 byte per character, with an encoding using 65,536 (216) values, which would require 2 bytes (16 bits) per character.
Two groups worked on this in parallel,ISO/IEC JTC 1/SC 2and theUnicode Consortium,the latter representing mostly manufacturers of computing equipment. The two groups attempted to synchronize their character assignments so that the developing encodings would be mutually compatible. The early 2-byte encoding was originally called "Unicode", but is now called "UCS-2".[1][2][11]
When it became increasingly clear that 216characters would not suffice,[12]IEEEintroduced a larger 31-bit space and an encoding (UCS-4) that would require 4 bytes per character. This was resisted by theUnicode Consortium,both because 4 bytes per character wasted a lot of memory and disk space, and because some manufacturers were already heavily invested in 2-byte-per-character technology. The UTF-16 encoding scheme was developed as a compromise and introduced with version 2.0 of the Unicode standard in July 1996.[13]It is fully specified in RFC 2781, published in 2000 by theIETF.[14][15]
UTF-16 is specified in the latest versions of both the international standardISO/IEC 10646and the Unicode Standard. "UCS-2 should now be considered obsolete. It no longer refers to an encoding form in either 10646 or the Unicode Standard."[1][2]UTF-16 will never be extended to support a larger number of code points or to support the code points that were replaced by surrogates, as this would violate the Unicode Stability Policy with respect to general category or surrogate code points.[16](Any scheme that remains aself-synchronizing codewould require allocating at least oneBasic Multilingual Plane(BMP) code point to start a sequence. Changing the purpose of a code point is disallowed.)
Description
[edit]Each Unicodecode pointis encoded either as one or two 16-bitcode units.Code points less than 216( "in the BMP" ) are encoded with a single 16-bit code unit equal to the numerical value of the code point, as in the older UCS-2. Code points greater than or equal to 216( "above the BMP" ) are encoded usingtwo16-bit code units. These two 16-bit code units are chosen from theUTF-16 surrogate range0xD800–0xDFFFwhich had not previously been assigned to characters. Values in this range are not used as characters, and UTF-16 provides no legal way to code them as individual code points. A UTF-16 stream, therefore, consists of single 16-bit codes outside the surrogate range, and pairs of 16-bit values that are within the surrogate range.
U+0000 to U+D7FF and U+E000 to U+FFFF
[edit]Both UTF-16 and UCS-2 encode code points in this range as single 16-bit code units that are numerically equal to the corresponding code points. These code points in theBasic Multilingual Plane(BMP) are theonlycode points that can be represented in UCS-2.[citation needed]As of Unicode 9.0, some modern non-Latin Asian, Middle-Eastern, and African scripts fall outside this range, as do mostemojicharacters.
Code points from U+010000 to U+10FFFF
[edit]Code points from the otherplanesare encoded as two 16-bitcode unitscalled asurrogate pair.The first code unit is ahigh surrogateand the second is alow surrogate(These are also known as "leading" and "trailing" surrogates, respectively, analogous to the leading and trailing bytes of UTF-8.[17]):
Low High
|
DC00 | DC01 | ... | DFFF |
---|---|---|---|---|
D800 | 010000 | 010001 | ... | 0103FF |
D801 | 010400 | 010401 | ... | 0107FF |
⋮ | ⋮ | ⋮ | ⋱ | ⋮ |
DBFF | 10FC00 | 10FC01 | ... | 10FFFF |
- 0x10000 is subtracted from the code point(U),leaving a 20-bit number(U')in the hex number range 0x00000–0xFFFFF.
- The high ten bits (in the range 0x000–0x3FF) are added to 0xD800 to give the first 16-bitcode unitorhigh surrogate(W1),which will be in the range0xD800–0xDBFF.
- The low ten bits (also in the range 0x000–0x3FF) are added to 0xDC00 to give the second 16-bitcode unitorlow surrogate(W2),which will be in the range0xDC00–0xDFFF.
Illustrated visually, the distribution ofU'betweenW1andW2looks like:[18]
U' = yyyyyyyyyyxxxxxxxxxx // U - 0x10000
W1 = 110110yyyyyyyyyy // 0xD800 + yyyyyyyyyy
W2 = 110111xxxxxxxxxx // 0xDC00 + xxxxxxxxxx
Since the ranges for thehigh surrogates(0xD800–0xDBFF),low surrogates(0xDC00–0xDFFF), and valid BMP characters (0x0000–0xD7FF, 0xE000–0xFFFF) aredisjoint,it is not possible for a surrogate to match a BMP character, or for two adjacentcode unitsto look like a legalsurrogate pair.This simplifies searches a great deal. It also means that UTF-16 isself-synchronizingon 16-bit words: whether a code unit starts a character can be determined without examining earlier code units (i.e. the type ofcode unitcan be determined by the ranges of values in which it falls). UTF-8 shares these advantages, but many earlier multi-byte encoding schemes (such asShift JISand other Asian multi-byte encodings) did not allow unambiguous searching and could only be synchronized by re-parsing from the start of the string. UTF-16 is not self-synchronizing if one byte is lost or if traversal starts at a random byte.
Because the most commonly used characters are all in the BMP, handling of surrogate pairs is often not thoroughly tested. This leads to persistent bugs and potential security holes, even in popular and well-reviewed application software (e.g.CVE-2008-2938,CVE-2012-2135).
U+D800 to U+DFFF (surrogates)
[edit]This sectionneeds additional citations forverification.(August 2023) |
The official Unicode standard says that no UTF forms, including UTF-16, can encode the surrogate code points. Since these will never be assigned a character, there should be no reason to encode them. However, Windows allows unpaired surrogates in filenames[19]and other places, which generally means they have to be supported by software in spite of their exclusion from the Unicode standard.
UCS-2, UTF-8, andUTF-32can encode these code points in trivial and obvious ways, and a large amount of software does so, even though the standard states that such arrangements should be treated as encoding errors.
It is possible to unambiguously encode anunpaired surrogate(a high surrogate code point not followed by a low one, or a low one not preceded by a high one) in the format of UTF-16 by using a code unit equal to the code point. The result is not valid UTF-16, but the majority of UTF-16 encoder and decoder implementations do this when translating between encodings.[citation needed]
Examples
[edit]To encode U+10437 (𐐷) to UTF-16:
- Subtract 0x10000 from the code point, leaving 0x0437.
- For the high surrogate, shift right by 10 (divide by 0x400), then add 0xD800, resulting in 0x0001 + 0xD800 = 0xD801.
- For the low surrogate, take the low 10 bits (remainder of dividing by 0x400), then add 0xDC00, resulting in 0x0037 + 0xDC00 = 0xDC37.
To decode U+10437 (𐐷) from UTF-16:
- Take the high surrogate (0xD801) and subtract 0xD800, then multiply by 0x400, resulting in 0x0001 × 0x400 = 0x0400.
- Take the low surrogate (0xDC37) and subtract 0xDC00, resulting in 0x37.
- Add these two results together (0x0437), and finally add 0x10000 to get the final code point, 0x10437.
The following table summarizes this conversion, as well as others. The colors indicate how bits from the code point are distributed among the UTF-16 bytes. Additional bits added by the UTF-16 encoding process are shown in black.
Character | Binary code point | Binary UTF-16 | UTF-16 hex code units |
UTF-16BE hex bytes |
UTF-16LE hex bytes | |
---|---|---|---|---|---|---|
$ | U+0024
|
0000 0000 0010 0100
|
0000 0000 0010 0100
|
0024
|
00 24
|
24 00
|
€ | U+20AC
|
0010 0000 1010 1100
|
0010 0000 1010 1100
|
20AC
|
20 AC
|
AC 20
|
𐐷 | U+10437
|
0001 0000 0100 0011 0111
|
1101 1000 0000 00011101 1100 0011 0111
|
D801DC37
|
D8 01DC 37
|
01 D837 DC
|
𤭢 | U+24B62
|
0010 0100 1011 0110 0010
|
1101 1000 0101 00101101 1111 0110 0010
|
D852DF62
|
D8 52DF 62
|
52 D862 DF
|
Byte-order encoding schemes
[edit]UTF-16 and UCS-2 produce a sequence of 16-bit code units. Since most communication and storage protocols are defined for bytes, and each unit thus takes two 8-bit bytes, the order of the bytes may depend on theendianness(byte order) of the computer architecture.
To assist in recognizing the byte order of code units,UTF-16allows abyte order mark(BOM), a code point with the value U+FEFF, to precede the first actual coded value.[nb 2](U+FEFF is the invisiblezero-width non-breaking space/ZWNBSP character.)[nb 3]If the endian architecture of the decoder matches that of the encoder, the decoder detects the 0xFEFF value, but an opposite-endian decoder interprets the BOM as thenoncharactervalue U+FFFE reserved for this purpose. This incorrect result provides a hint to perform byte-swapping for the remaining values.
If the BOM is missing, RFC 2781 recommends[nb 4]that big-endian (BE) encoding be assumed. In practice, due to Windows using little-endian (LE) order by default, many applications assume little-endian encoding. It is also reliable to detect endianness by looking for null bytes, on the assumption that characters less than U+0100 are very common. If more even bytes (starting at 0) are null, then it is big-endian.
The standard also allows the byte order to be stated explicitly by specifyingUTF-16BEorUTF-16LEas the encoding type. When the byte order is specified explicitly this way, a BOM is specificallynotsupposed to be prepended to the text, and a U+FEFF at the beginning should be handled as a ZWNBSP character. Most applications ignore a BOM in all cases despite this rule.
ForInternetprotocols,IANAhas approved "UTF-16", "UTF-16BE", and "UTF-16LE" as the names for these encodings (the names are case insensitive). The aliasesUTF_16orUTF16may be meaningful in some programming languages or software applications, but they are not standard names in Internet protocols.
Similar designations,UCS-2BEandUCS-2LE,are used to show versions ofUCS-2.
Size
[edit]A "character" may use any number of Unicode code points.[20]For instance anemoji flag charactertakes 8 bytes, since it is "constructed from a pair of Unicode scalar values"[21](and those values are outside the BMP and require 4 bytes each). UTF-16 in no way assists in "counting characters" or in "measuring the width of a string".
UTF-16 is often claimed to be more space-efficient thanUTF-8for East Asian languages, since it uses two bytes for characters that take 3 bytes in UTF-8. Since real text contains many spaces, numbers, punctuation, markup (for e.g. web pages), and control characters, which take only one byte in UTF-8, this is only true for artificially constructed dense blocks of text.[citation needed]A more serious claim can be made forDevanagariandBengali,which use multi-letter words and all the letters take 3 bytes in UTF-8 and only 2 in UTF-16.
In addition the Chinese Unicode encoding standardGB 18030always produces files the same size or smaller than UTF-16 for all languages, not just for Chinese (it does this by sacrificing self-synchronization).
Usage
[edit]UTF-16 is used for text in the OSAPIof all currently supported versions ofMicrosoft Windows(and including at least all sinceWindows CE/2000/XP/2003/Vista/7[22]) includingWindows 10.In Windows XP, no code point above U+FFFF is included in any font delivered with Windows for European languages.[23][24]OlderWindows NTsystems (prior to Windows 2000) only supportUCS-2.[25]Files and network data tend to be a mix of UTF-16, UTF-8, and legacy byte encodings.
While there's been some UTF-8 support for even Windows XP,[26]it wasimproved(in particular the ability to name a file using UTF-8) in Windows 10insider build17035 and the May 2019 update. As of May 2019,Microsoft recommends software use UTF-8,on Windows andXbox,instead of other 8-bit encodings.[27]It is unclear if they are recommending usage of UTF-8 over UTF-16, though they do state "UTF-16 [..] is a unique burden that Windows places on code that targets multiple platforms."[28]
TheIBM ioperating system designatesCCSID(code page) 13488 for UCS-2 encoding and CCSID 1200 for UTF-16 encoding, though the system treats them both as UTF-16.[29]
UTF-16 is used by theQualcomm BREWoperating systems; the.NETenvironments; and theQtcross-platform graphicalwidget toolkit.
Symbian OSused in Nokia S60 handsets and Sony EricssonUIQhandsets uses UCS-2.iPhonehandsets use UTF-16 forShort Message Serviceinstead of UCS-2 described in the3GPP TS 23.038(GSM) and IS-637 (CDMA) standards.[30]
TheJoliet file system,used inCD-ROMmedia, encodes file names using UCS-2BE (up to sixty-four Unicode characters per file name).
Pythonversion 2.0 officially only used UCS-2 internally, but the UTF-8 decoder to "Unicode" produced correct UTF-16. There was also the ability to compile Python so that it used UTF-32 internally, this was sometimes done on Unix. Python 3.3 switched internal storage to use one ofISO-8859-1,UCS-2, or UTF-32 depending on the largest code point in the string.[31]Python 3.12 drops some functionality (for CPython extensions) to make it easier to migrate toUTF-8for all strings.[32]
Javaoriginally used UCS-2, and added UTF-16 supplementary character support inJ2SE 5.0.Recently they have encouraged dumping support for any 8-bit encoding other than UTF-8[33]but internally UTF-16 is still used.
JavaScriptmay use UCS-2 or UTF-16.[34]As of ES2015, string methods and regular expression flags have been added to the language that permit handling strings from an encoding-agnostic perspective.
UEFIuses UTF-16 to encode strings by default.
Swift,Apple's preferred application language, used UTF-16 to store strings until version 5 which switched to UTF-8.[35]
Quite a few languages make the encoding part of the string object, and thus store and support a large set of encodings including UTF-16. Most consider UTF-16 and UCS-2 to be different encodings. Examples are thePHPlanguage[36]andMySQL.[37]
A method to determine what encoding a system is using internally is to ask for the "length" of string containing a single non-BMP character. If the length is 2 then UTF-16 is being used. 4 indicates UTF-8. 3 or 6 may indicateCESU-8.1mayindicate UTF-32, but more likely indicates the language decodes the string to code points before measuring the "length".
In many languages, quoted strings need a new syntax for quoting non-BMP characters, as the C-style"\uXXXX"
syntax explicitly limits itself to 4 hex digits. The following examples illustrate the syntax for the non-BMP characterU+1D11E𝄞MUSICAL SYMBOL G CLEF:
- The most common (C++,C#,D,and several other languages) is an upper-case 'U' with8hex digits such as
"\U0001D11E"
.[38] - Java 7 regular expressions,ICU,and Perl, use
"\x{1D11E}"
. - ECMAScript2015 (JavaScript) uses
"\u{1D11E}"
. - In many other cases (such as Java outside of regular expressions),[39]the only way to get non-BMP characters is to enter the surrogate halves individually:
"\uD834\uDD1E"
.
See also
[edit]Notes
[edit]- ^UTF-32 is also incompatible with ASCII, but is not listed as a web-encoding.[7]
- ^UTF-8 encoding produces byte values strictly less than 0xFE, so either byte in the BOM sequence also identifies the encoding as UTF-16 (assuming that UTF-32 is not expected).
- ^Use of U+FEFF as the character ZWNBSP instead of as a BOM has been deprecated in favor of U+2060 (WORD JOINER); seeByte Order Mark (BOM) FAQat Unicode.org. But if an application interprets an initial BOM as a character, the ZWNBSP character is invisible, so the impact is minimal.
- ^RFC2781section 4.3 says that if there is no BOM, "the text SHOULD be interpreted as being big-endian." According to section 1.2, the meaning of the term "SHOULD" is governed byRFC2119.In that document, section 3 says "... there may exist valid reasons in particular circumstances to ignore a particular item, but the full implications must be understood and carefully weighed before choosing a different course".
References
[edit]- ^abc"C.2 Encoding Forms in ISO/IEC 10646"(PDF).The Unicode Standard, version 6.0.Mountain View, CA:Unicode Consortium.February 2011. p. 573.ISBN978-1-936213-01-6.
[...] the term UCS-2 should now be considered obsolete. It no longer refers to an encoding form in either 10646 or the Unicode Standard.
- ^abc"FAQ: What is the difference between UCS-2 and UTF-16?".unicode.org.Archived fromthe originalon 2003-08-18.Retrieved2024-03-19.
UCS-2 is obsolete terminology which refers to a Unicode implementation up to Unicode 1.1 [...]
- ^"What is UTF-16?".The Unicode Consortium.Unicode, Inc.Retrieved7 January2023.
UTF-16 uses a single 16-bit code unit to encode over 60,000 of the most common characters in Unicode
- ^Lunde, Ken (2022-01-09)."2022 Top Ten List: Why Support Beyond-BMP Code Points?".Medium.Retrieved2024-01-07.
I first came up with the idea for this Top Ten List over 10 years ago, which was prompted by some environments that still supported only BMP code points. The idea, of course, was to motivate the developers of such environments to support code points beyond the BMP by providing an enumerated list of reasons to do so. And yes, there are still some environments that support only BMP code points, such as the VivaDesigner app.
- ^Chad Selph (2012-11-08)."Adventures in Unicode SMS".Twilio. Archived fromthe originalon 2015-09-08.Retrieved2015-08-28.
- ^"HTML Living Standard".w3.org.2020-06-10. Archived fromthe originalon 2020-09-08.Retrieved2020-06-15.
UTF-16 encodings are the only encodings that this specification needs to treat as not being ASCII-compatible encodings.
- ^"Encoding Standard".encoding.spec.whatwg.org.Retrieved2023-04-22.
- ^"Usage Statistics of UTF-16 for Websites, January 2024".w3techs.Retrieved2024-01-07.
- ^"Usage Statistics of UTF-8 for Websites, December 2023".w3techs.Retrieved2023-12-01.
- ^"Encoding Standard".encoding.spec.whatwg.org.Retrieved2018-10-22.
The UTF-8 encoding is the most appropriate encoding for interchange of Unicode, the universal coded character set. Therefore for new protocols and formats, as well as existing formats deployed in new contexts, this specification requires (and defines) the UTF-8 encoding. [..] The problems outlined here go away when exclusively using UTF-8, which is one of the many reasons that UTF-8 is now the mandatory encoding for all text things on the Web.
- ^"MySQL:: MySQL 5.7 Reference Manual:: 10.1.9.4 The ucs2 Character Set (UCS-2 Unicode Encoding)".dev.mysql.
- ^"What is UTF-16?".The Unicode Consortium.Unicode, Inc.Retrieved29 March2018.
- ^"Questions about encoding forms".Retrieved2010-11-12.
- ^ISO/IEC 10646:2014 "Information technology – Universal Coded Character Set (UCS)" sections 9 and 10.
- ^The Unicode Standardversion 7.0 (2014)section 2.5.
- ^"Unicode Character Encoding Stability Policies".unicode.org.
- ^Allen, Julie D.; Anderson, Deborah;Becker, Joe;Cook, Richard, eds. (2014)."3.8 Surrogates"(PDF).The Unicode Standard, Version 7.0—Core Specification.Mountain View:The Unicode Consortium.p. 118.Archived(PDF)from the original on 2022-10-09.Retrieved3 November2014.
- ^Yergeau, Francois; Hoffman, Paul (February 2000)."UTF-16, an encoding of ISO 10646".tools.ietf.org.Retrieved2019-06-18.
- ^"Maximum Path Length Limitation".Microsoft.2022-07-18.Retrieved2022-10-10.
[…] the file system treats path and file names as an opaque sequence of WCHARs
- ^"It's not wrong that" 🤦🏼♂️ ".length == 7".hsivonen.fi.Retrieved2021-03-15.
- ^"Apple Developer Documentation".developer.apple.Retrieved2021-03-15.
- ^Unicode (Windows).Retrieved 2011-03-08 "These functions use UTF-16 (wide character) encoding (…) used for native Unicode encoding on Windows operating systems."
- ^"Unicode".microsoft.Retrieved2009-07-20.
- ^"Surrogates and Supplementary Characters".microsoft.Retrieved2009-07-20.
- ^"Description of storing UTF-8 data in SQL Server".microsoft. 7 December 2005.Retrieved2008-02-01.
- ^"[Updated] Patch for cmd.exe for windows xp for cp 65001 - Page 2 - DosTips".dostips.Retrieved2021-06-17.
- ^"Use UTF-8 code pages in Windows apps".learn.microsoft.Retrieved2020-06-06.
As of Windows version 1903 (May 2019 update), you can use the ActiveCodePage property in the appxmanifest for packaged apps, or the fusion manifest for unpackaged apps, to force a process to use UTF-8 as the process code page. [...]
CP_ACP
equates toCP_UTF8
only if running on Windows version 1903 (May 2019 update) or above and the ActiveCodePage property described above is set to UTF-8. Otherwise, it honors the legacy system code page. We recommend usingCP_UTF8
explicitly. - ^"UTF-8 support in the Microsoft Game Development Kit (GDK) - Microsoft Game Development Kit".learn.microsoft.Retrieved2023-03-05.
By operating in UTF-8, you can ensure maximum compatibility [..] Windows operates natively in UTF-16 (or WCHAR), which requires code page conversions by using MultiByteToWideChar and WideCharToMultiByte. This is a unique burden that Windows places on code that targets multiple platforms. [..] The Microsoft Game Development Kit (GDK) and Windows in general are moving forward to support UTF-8 to remove this unique burden of Windows on code targeting or interchanging with multiple platforms and the web. Also, this results in fewer internationalization issues in apps and games and reduces the test matrix that's required to get it right.
- ^"UCS-2 and its relationship to Unicode (UTF-16)".IBM.Retrieved2019-04-26.
- ^Selph, Chad (2012-11-08)."Adventures in Unicode SMS".Twilio. Archived fromthe originalon 2012-11-09.Retrieved2015-08-28.
- ^"PEP 0393 – Flexible String Representation".Python.org.Retrieved2015-05-29.
- ^"PEP 623 – Remove wstr from Unicode | peps. Python.org".peps. Python.org.Retrieved2023-02-24.
- ^"JEP 400: UTF-8 by Default".openjdk.org.Retrieved2023-03-12.
- ^"JavaScript's internal character encoding: UCS-2 or UTF-16? · Mathias Bynens".
- ^"UTF-8 String".Swift.org.2019-03-20.Retrieved2020-08-20.
- ^"PHP: Supported Character Encodings - Manual".php.net.
- ^"MySQL:: MySQL 8.0 Reference Manual:: 10.9.2 The utf8mb3 Character Set (3-Byte UTF-8 Unicode Encoding)".dev.mysql.Retrieved2023-02-24.
- ^"ECMA-334: 9.4.1 Unicode escape sequences".en.csharp-online.net.Archived fromthe originalon 2013-02-15.
- ^Lexical Structure: Unicode Escapesin"The Java Language Specification, Third Edition".Sun Microsystems, Inc.2005.Retrieved2019-10-11.
External links
[edit]- A very short algorithm for determining the surrogate pair for any code point
- Unicode Technical Note #12: UTF-16 for Processing
- Unicode FAQ: What is the difference between UCS-2 and UTF-16?
- Unicode Character Name Index
- RFC2781:UTF-16, an encoding of ISO 10646
- java.lang.String documentation, discussing surrogate handling