Tekstcodering: ASCII en UTF-8
Computers slaan alles op als getallen. Maar hoe bewaar je tekst als getallen? Dat vereist een afgesproken coderingstabel die elk karakter koppelt aan een getal.
ASCII
ASCII (American Standard Code for Information Interchange) was de eerste brede standaard, gepubliceerd in 1963. Het gebruikt 7 bits — genoeg voor 128 karakters.
De tabel omvat:
- Grote en kleine letters (A–Z, a–z)
- Cijfers (0–9)
- Leestekens en speciale tekens
- Controlekarakters (newline, tab, ...)
| Karakter | Decimaal | Hex | Binair |
|---|---|---|---|
A | 65 | 0x41 | 0100 0001 |
B | 66 | 0x42 | 0100 0010 |
a | 97 | 0x61 | 0110 0001 |
Z | 90 | 0x5A | 0101 1010 |
0 | 48 | 0x30 | 0011 0000 |
space | 32 | 0x20 | 0010 0000 |
! | 33 | 0x21 | 0010 0001 |
De ASCII-waarden van A–Z lopen van 65 tot 90, die van a–z van 97 tot 122. Het verschil is precies 32 — of in binair: bit 5. Dat is geen toeval: je kunt met een XOR van 32 wisselen tussen hoofd- en kleine letters.
// JavaScript
"A".charCodeAt(0) // 65
("A".charCodeAt(0) ^ 32) // 97 → "a"
String.fromCharCode(65 ^ 32) // "a"
// C#
(int)'A' // 65
(int)'A' ^ 32 // 97
(char)((int)'A' ^ 32) // 'a'
Het probleem van ASCII
ASCII was ontworpen voor het Engelse alfabet. Accenten, Grieks, Arabisch, Chinees, emoji — allemaal niet voorzien. Met 7 bits en 128 tekens kom je er niet ver.
Er kwamen honderden incompatibele uitbreidingen. Een bestand opgeslagen in een West-Europese codering werd onleesbaar in een andere codering. Dat probleem kent iedereen die ooit een e-mail met ’ of é ontvangen heeft — dat zijn fout geïnterpreteerde bytes.
Unicode
Unicode lost dit op met een universele tekenset van meer dan 140.000 karakters. Elk karakter krijgt een uniek getal — een code point — geschreven als U+ gevolgd door een hexadecimaal getal:
| Karakter | Code point |
|---|---|
é | U+00E9 |
€ | U+20AC |
中 | U+4E2D |
🔥 | U+1F525 |
😀 | U+1F600 |
Unicode bepaalt welk getal elk karakter heeft. Hoe je dat getal opslaat in bytes is een aparte vraag.
UTF-8: Unicode in de praktijk
UTF-8 is de meest gebruikte manier om Unicode-tekst op te slaan. Het gebruikt 1 tot 4 bytes per karakter, afhankelijk van de grootte van het code point:
| Code point | Bytes | Voorbeelden |
|---|---|---|
| U+0000 – U+007F | 1 byte | Alle ASCII-tekens (A, !, 5) |
| U+0080 – U+07FF | 2 bytes | Accenten (é, ñ, ü) |
| U+0800 – U+FFFF | 3 bytes | Niet-Latijnse schriften (中, €, →) |
| U+10000 – U+10FFFF | 4 bytes | Emoji en zeldzame symbolen (😀, 🔥) |
Het grote voordeel: alle ASCII-tekens zijn in UTF-8 identiek — A is nog steeds byte 0x41. UTF-8 is volledig achterwaarts compatibel met ASCII.
Bijna alle webpagina's gebruiken UTF-8. Vandaar die regel bovenaan elk HTML-bestand:
<meta charset="UTF-8">
Zonder deze tag kan de browser de bytes verkeerd interpreteren en verschijnen er onleesbare tekens.
Tekens in code
In JavaScript en C# kun je rechtstreeks met karaktercodes werken:
// JavaScript
"A".charCodeAt(0) // 65
String.fromCharCode(65) // "A"
"€".codePointAt(0) // 8364 (U+20AC)
"😀".codePointAt(0) // 128512 (U+1F600)
// C#
(int)'A' // 65
(char)65 // 'A'
(int)'€' // 8364 (€)
char.ConvertToUtf32("😀", 0) // 128512
Dit maakt duidelijk waarom tekst in de informatica uiteindelijk gewoon getallen is — en waarom talstelsels zo fundamenteel zijn.
Interactief verkennen
Wil je zelf zien hoe tekst omgezet wordt naar bytes, ASCII-waarden en Unicode code points? Of wat er precies misgaat als een tekst in de verkeerde codering gelezen wordt (Mojibake)? Probeer het zelf:
De tool toont stap voor stap hoe tekens codering ingaan en hoe Mojibake ontstaat — het soort onleesbare output (’, é) dat je vast al eens tegengekomen bent.