Over Unicode

Wat is Unicode nou eigenlijk?
Unicode is een wereldwijd consortium, dat de gelijknamige standaard heeft bedacht om alles wat mensen schrijven in een enkele set vast te leggen, met een uniek nummer voor alle denkbare karakters: letters, leestekens, besturingstekens, symbolen, smileys en zelfs zelfverzonnen symbolen.
Er zijn ruwweg 1.114.112 karakters gedefineerd, en Unicode is tot op de dag van vandaag aan verandering onderhevig.
Zie ook: http://unicode.org/history/publicationdates.html

Waarom is er Unicode?
Het is een oplossing voor een steeds terugkerend probleem met alle computers, PC's, Mac's, UNIX-en, en mainframes.
Karakters worden in karaktersets opgeslagen, maar niet alle karakters passen in een set. Dat komt omdat men zich beperkte tot 7 bits voor de opslag, wat ruimte biedt aan 128 unieke nummers (codepoints), die corresponderen met 128 unieke karakters.
Het had als gevolg dat voor elke set een keuze gemaakt moest worden. Welke karakters komen in welke volgorde in de set?
Er werden veel verschillende sets gemaakt, die uiteraard niet volledig compatible waren.
Het omzetten van de ene bronkarakterset naar de doelkarakterset (transcoding) is goed te doen als karakters in beide sets aanwezig zijn.
Dan hoeven alleen de codepoints omgenummerd te worden. Het grote probleem komt wanneer de benodigde karakters niet in de doelkarakterset aanwezig zijn. Dan treedt er verlies van data en dus meestal altijd verlies van betekenis op, waardoor data en ook programmatuur corrupt raakt.

Wat waren de problemen?
Computers waren beperkt, omdat bytes duur waren. Aanvankelijk waren er 7 bits beschikbaar: 7 data bits en 1 pariteitsbit. In 1986 werd de meest recente versie van (US-)ASCII ontwikkeld, een standaard van 128 karaketers om gegevensuitwisseling tussen verschillende computers mogelijk te maken. Het is nog steeds de standaard op UNIX- en PC-machines.
Naarmate er mondiaal meer gegevens digitaal uitgewisseld werden, nam de behoefte toe aan meer verschillende karakters.
Door de pariteitsbit te gebruiken als data bit konden nog eens 128 karakters worden opgeslagen, ook wel bekend als de Extended ASCII-set. Voor de laatste 128 karakters werden wederom vele verschillende subsets (codepages) bedacht, met dezelfde oude transcodingsproblematiek.

Wat zijn de problemen nu dan nog?
In de Westerse wereld wordt de codepage Latin1 (ISO/IEC-8859-1) als aanvulling op ASCII gebruikt.
Helaas bestaat daarover de nodige verwarring, omdat Microsoft een tweede, veelgebruikte Extended ASCII codepage (CP-1252) heeft ontwikkeld voor Latijnse talen. Deze wordt toegepast vanuit DOS/Windows op PC's, waardoor consistente gegevensuitwisseling met andere systemen (Apple, UNIX, mainframe) bemoeilijkt wordt.
Maar ook tussen andere bestaande karaktersets bestaat nog steeds hetzelfde probleem van gegevensverlies bij transcoding.
Dit komt -- niet toevallig -- het meest in zicht via het internet. Tussen allerlei talen worden gegevens uitgewisseld. Vroeger per fax, nu volledig digitaal. En de verschillende manieren waarop karakters worden opgeslagen maken het regelmatig tot een logische uitdaging.
Tegelijkertijd is het probleem ontzettend onzichtbaar. We zien alleen de beeldpunten van het scherm, of de inktpunten op papier die de karakters vormen. De onderliggende bits en bytes kunnen we alleen goed zien met aparte software als een HEX-editor.

En de oplossing is Unicode?
Door elk bestaand karakter een eigen codepoint te geven, kan er geen verwarring bestaan over welk karakter bedoeld wordt.
Er kan altijd naar Unicode getranscodeerd worden. Dat is de grootste waarde van Unicode.
Toch lost dat nog niet alle problemen op.
Een groot probleem met Unicode is echter dat het totaal aantal codepoints niet te vatten is in één enkele byte. Daarmee breekt het gebruik van Unicode met de meeste bestaande programmeertalen, waarin de aanname is gedaan dat 1 byte gelijkstaat aan 1 karakter. Dit is dusdanig backward incompatible dat het niet gelukt is PHP 6 van de grond te krijgen. Het probleem blijft niet bepert tot PHP, alle programmeertalen, ook die in databases hebben met encoding te maken en hebben hiervoor een eigen oplossing. PHP 7 voorziet weinig verbetering op dit vlak, zie ook de migration guide op: http://php.net/manual/en/migration70.php
Een kleiner probleem is dat lang niet alle karakters door de meeste lettertype ondersteund worden.

Maar hadden we voor het web niet al UTF-8?
Bij een Single Byte Character Set (SBCS) waarbij 1 byte gelijk staat aan 1 karakter, is de codepoint direct te vertalen naar karakter. Met Unicode is het concept van hoe de codepoints worden genummerd, losgeweekt van hoe de codepoints worden opgeslagen (encoding). Om Unicode op te slaan zijn er verschillende encodings ontwikkeld, de meeste bekende zijn: UTF-8, UTF-16 en UTF-32.
Maar er zijn er nog veel meer: UTF-1, UTF-7, UTF-EBCDIC, SCSU, BOCU, etc.
Alle Unicode encodings zijn een Multi Byte Character Set (MBCS), en sommige (waaronder UTF-8) zijn variabel in lengte (VMBCS). Met UTF-8 kan 1 karakter 1 tot en met 6 bytes in beslag nemen.
Voor het web (HTML5 en JavaScript) is gekozen voor UTF-8 als standaard-encoding.

Waarom UTF-8?
Het heeft als belangrijk voordeel dat ASCII volledig compatible is met Unicode. Beter nog: ASCII hoeft niet naar UTF-8 getranscodeerd, het is al een subset van UTF-8. Hierdoor worden eventuele problemen met data en programmatuur met de meestgebruike UNIX- en PC-systemen zoveel mogelijk vermeden.
Een tweede voordeel is dat UTF-8 de karakters opslaat in groepjes van losse bytes. UTF-8 is variabel in lengte, karakters worden in 1 byte t/m 6 bytes opgeslagen. Daarmee worden ook problemen tussen Little Endian en Big Endian systemen vermeden. Daardoor is ook een speciaal Unicode karakter, de Byte Order Mark (BOM), optioneel bij UTF-8, terwijl het vereist is bij andere MBCS-encodings. De enige noodzaak om een BOM te gebruiken is om tekst-editors te hinten dat de tekst als UTF-8 is opgeslagen.
Met UTF-8 wordt het voordeel van Unicode behouden, en transcoding tussen andere Unicode-encodings is geen probleem.

Technisch zijn er twee voordelen waarom UTF-8 de voorkeur heeft boven andere encodings:
Ten eerste heeft UTF-8 geen codepoint waarbij er in 1 byte alleen maar 8 nullen voorkomen. Dit speciale NUL-karakter geeft in veel programmeertalen het einde aan van een string, waarna de overige bytes genegeerd worden.
Ten tweede kan je vanaf elk willekeurige byte eenvoudig een vorig of volgend karakter kan aanwijzgen. Het is mogelijk omdat de eerste byte van een groepje altijd in de eerste bit een 0 bevat, of 11 in de eerste twee bits. Dat aspect wordt zelfsynchronisatie genoemd en is handig bij streams.

Hoe staat PHP ten opzichte van Unicode?
Er gaat een gerucht dat PHP 5 agnostisch is ten opzichte van encoding. Maar dat klopt niet helemaal: de encoding waarin .php-bestanden moeten worden opgeslagen moet (US-)ASCII compatible zijn.
Zie ook: http://php.net/manual/en/mbstring.php4.req.php
PHP gaat in de aanwezige functies voor de programmeur standaard uit van Latin1 (ISO/IEC-8859-1).
Er is beperkte ondersteuning voor UTF-8, met utf8_* -functies, en de mb_* functies.
De rest wordt aan de individuele programmeur overgelaten. PHP 5 is daarin niet uniek.
PHP 6 zou verandering brengen maar is helaas gestrand.
PHP 7 staat voor de deur, met enkele verbeteringen op het gebied van Unicode.

« Lees de omschrijving en reacties

Inhoudsopgave

  1. Inleiding
  2. Over Unicode
  3. PHP en UTF-8
  4. Tekstbestanden
  5. Databases
  6. Overige in- en uitvoer
  7. Verwerking in PHP
  8. Conclusie

PHP tutorial opties

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.