# UTF-16

UTF-16, 16-bit Unicode Transformation Format, is een tekencodering met een variabele lengte, die de gehele Unicode-tekenset ondersteunt.
De codeerstandaard zet karakters om vanuit een Unicode-codepoint naar een reeks van 16-bitwoorden. Karakters uit het Basic Multilingual Plane (BMP) kunnen worden omgezet naar één woord van 16 bits. De karakters daarboven worden omgezet in twee woorden (een zogenoemd surrogaatpaar).
Alle codepoints van U+0000 tot en met U+10FFFF (behalve de oneigenlijke codepoints U+D800–U+DFFF en codepoints voor toekomstig gebruik) kunnen worden omgezet naar UTF-16.
Omdat veel computers rekenen in eenheden van bytes, zijn er drie gerelateerde encoding-schema's: UTF-16, UTF-16BE en UTF-16LE. Ze verschillen alleen in de byte order (bytevolgorde) om een 16-bit-eenheid voor te stellen. Alle schema's resulteren in óf een 2- óf een 4-bytereeks voor een karakter.
UTF-16 is officieel gedefinieerd in bijlage Q van de internationale standaard ISO/IEC 10646-1. Het staat ook beschreven in de Unicode-standaard, versie 3.0 en hoger, alsmede in RFC 2781 van IETF.
UCS-2 (2-byte Universal Character Set) is een incourante manier om karakters te coderen. UCS-2 is een voorloper van UTF-16. De UCS-2-standaard is bijna identiek aan UTF-16, behalve dat het geen surrogaatparen ondersteunt en daarom alleen de karakters in het BMP-bereik (van U+0000 t/m U+FFFF) kan coderen.
De consequentie van deze vaste-lengtecodering is dat elk karakter een 16-bitwaarde voorstelt. UTF-16 kent drie gerelateerde codeerschema's (UCS-2, UCS-2BE, UCS-2LE) die alle karakters kunnen opleveren in een specifieke bytevolgorde.
Vanwege de technische verwantschap en opwaartse compatibiliteit van UCS-2 naar UTF-16 worden de twee standaarden vaak foutief door elkaar gehaald en uitwisselbaar genoemd. Dat wil zeggen, er wordt gezegd dat tekenreeksen die zijn gecodeerd in UTF-16 soms foutief als UCS-2 worden herkend.
Voor zowel UTF-16 als UCS-2 geldt dat alle 65.536 codepoints in BMP (vlak 0), met uitzondering van de 2048 speciale tekens, overeenkomen met dezelfde gecodeerde waardes. Dus codepoint U+0000 is gecodeerd als nummer 0 en U+FFFF is gecodeerd als 65.535 (dat is FFFF$_{16}$ in hexadecimaal).

## Vertalen van karakters buiten de BMP

UTF-16 kan in tegenstelling tot UCS-2 ook karakters coderen van Unicode-panelen 1–16, dus niet alleen vlak 0 (BMP).
UTF-16 vertaalt de non-BMP-karakters (die van U+10000 tot en met U+10FFFF) in twee 16-bitwoorden, ook wel bekend als een surrogate pair (surrogaatpaar). Eerst wordt er 10000$_{hex}$ afgetrokken van het codepoint om een 20-bitwaarde te krijgen. Dit wordt dan opgedeeld in twee onafhankelijke 10-bitwaardes, waarbij elke 10-bitwaarde een surrogaatpaar voorstelt met het meest significante paar in het eerste woord. Om op een veilige manier woordgeoriënteerde strings te kunnen verwerken, zijn er twee bereiken gedefinieerd. Het eerste surrogaat valt in (U+D800–U+DBFF) en het tweede surrogaat valt in (U+DC00–U+DFFF).
Zo wordt bijvoorbeeld het karakter van codepoint U+10000 omgezet naar de reeks D800 DC00 (hexadecimaal). Het karakter op U+10FFFD, de bovengrens van Unicode, wordt omgezet naar de reeks DBFF DFFD. Unicode en ISO/IEC 10646 kennen geen karakters toe aan codepoints tussen D800–DFFF, om een individuele codering van een surrogaatpaar nooit een karakter te laten voorstellen.

## Volgorde van bytes

Zowel de UTF-16- als de UCS-2-vertalingen produceren karakters in een reeks van 16-bitwoorden. Deze reeks kan niet zonder meer worden uitgewisseld tussen computers, vanwege de endianness van een computer. Om dit probleem op te lossen, zijn er drie verschillende karaktercodeerschema's bedacht:
Voor UTF-16 zijn er de schema's:
* UTF-16
* UTF-16BE
* UTF-16LE
En voor UCS-2 zijn er de schema's:
* UCS-2
* UCS-2BE
* UCS-2LE
Het UTF-16-codeerschema (en ook dat van UCS-2) ondersteunt beide endianrepresentaties, maar verwacht dat de bytevolgorde wordt aangegeven door een byte order mark vooraan de tekenreeks. Deze BOM wordt voorgesteld door het Zero-Width No-Break Space-karakter (ZWNBSP), codepoint U+FEFF, omdat het nooit aan het begin van data zou moeten staan. Dit resulteert in de bytevolgorde FE FF (in hexadecimaal) voor een big-endianarchitectuur en FF FE voor een little-endianarchitectuur. De BOM in het begin van UTF-16- en UCS-2-gecodeerde data wordt beschouwd als de handtekening van de data zelf en dient voor de decoder. Technisch gezien is bij het UTF-16-schema de BOM-voorloop optioneel, maar het weglaten hiervan wordt niet aanbevolen, omdat dan UTF-16LE of UTF-16BE eigenlijk gebruikt zouden moeten worden. Als de BOM niet aanwezig is en elke andere indicatie van de bytevolgorde in hogere protocollen ontbreekt, dan moet big-endian gebruikt worden. De BOM is in UCS-2 niet optioneel.
Het UTF-16BE- en UTF-16LE-codeerschema (en het corresponderende UCS-2BE en UCS-2LE) is vergelijkbaar met het UTF-16- en het UCS-2-codeerschema. Echter, in plaats van de data door een BOM te laten voorafgaan, wordt de bytevolgorde aangegeven door de naam van het codeerschema (LE voor little-endian, BE voor big-endian). Omdat de BOM uitdrukkelijk niet aan deze schema's vooraf mag gaan, zal een gecodeerd ZWNBSP-karakter aan het begin van de data niet als een BOM worden opgevat, maar als deel van de tekst zelf. In de praktijk zal software een BOM die "per ongeluk" voorkomt in UTF-LE- en UTF-BE-gecodeerde tekst alsnog negeren.
Het IANA heeft met exact de volgende namen (hoofdletterongevoelig) UTF-16, UTF-16BE en UTF-16LE voor het gebruik op internet geaccordeerd. De synoniemen UTF_16 en UTF16 kunnen in bepaalde programmeertalen of programma's een betekenis hebben, maar zijn niet gedefinieerd in de internetprotocollen.

## Gebruik in de meest gangbare besturingssystemen en omgevingen

UTF-16 wordt gebruikt als interne representatie van tekst in de besturingssystemen Microsoft Windows NT/2000/XP/CE, in Qualcomm BREW, de programmeertaal Java, .NET en ECMAScript, Mac OS X's framework Cocoa and Core Foundation en de cross-platform, grafische widgettoolkit Qt.
Symbian OS, dat wordt gebruikt in de mobiele telefoons Nokia S60 en Sony Ericsson UIQ, gebruikt intern UCS-2.
Oudere Windows NT-machines (vóór Windows 2000) ondersteunen alleen UCS-2. De programmeertaal Python ondersteunt UTF-16 sinds versie 2.1, maar nieuwere versies van Python ondersteunen UCS-4 om karakters op te slaan (in plaats van UTF-16).

## Voorbeelden

| codepoint | karakter | UTF-16-waarde(s) | glief* |
| 122 (hex 7A) | kleine Z (Latijn) | 007A | z |
| 27700 (hex 6C34) | water (Chinees) | 6C34 | 水 |
| 119070 (hex 1D11E) | vioolsleutel | D834 DD1E | 𝄞 |
"水z𝄞" (water, z, vioolsleutel), naar UTF-16 omgezet :
| Codering | bytevolgorde | bytereeks |
| UTF-16LE | little-endian | 34 6C, 7A 00, 34 D8 1E DD |
| UTF-16BE | big-endian | 6C 34, 00 7A, D8 34 DD 1E |
| UTF-16 | little-endian, met BOM | FF FE, 34 6C, 7A 00, 34 D8 1E DD |
| UTF-16 | big-endian, met BOM | FE FF, 6C 34, 00 7A, D8 34 DD 1E |
* Een geschikt lettertype moet zijn geïnstalleerd om deze karakters correct weer te geven.

### Voorbeeld van een UTF-16-vertaling

Men wil het karakter op codepoint U+64321 (hexadecimaal) omzetten naar UTF-16. Omdat dit karakter boven de U+FFFF is, moet dit karakter worden omgezet naar een paar van 16-bitwoorden.
Dus de correcte vertaling naar UTF-16 van dit karakter is: 0xD950 0xDF21
Omdat het karakter boven de U+FFFF is, kan dit karakter niet worden omgezet naar UCS-2.