Jag tar upp Unicode eftersom Javas användning av Unicode kan vara lite förvirrande och motsägelsefull. Det som följer är inte en komplett utredning av problematiken utan bara en introduktion. Jag ger också några exempel på hur man kan arbeta med Unicode i Java. Mer information om Unicode hittar du här: http://unicode.org/. Du kan även titta på Wikipedia-artikeln om Unicode. Oracle har en tutorial om Unicode.
Unicode är en plattformsoberoende representation av olika tecken. Målet med Unicode är att koda alla världens alfabet (inklusive de som har använts för språk som numera är utdöda).
Ibland säger man att Javas primitiva datatyp char
lagrar ett tecken
men det är lätt att inse att detta inte kan stämma om man använder
Unicode. En char
är 16 bitar. Med 16 bitar kan man representera max
65536 olika tecken. Om vi ska lagra bokstäver från alla världens språk
behöver vi mera utrymme.
Faktum är att dagens unicode-standard innehåller (i mars 2025) 154 998
tecken. Detta innebär att minsta datatypen i Java som kodar alla
tecken är int
. För att slippa använda 32 bitar för varje tecken
använder man olika avkodningar (encodings) som kodar Unicode till en
sekvens av bytes eller 16-bitars ord. Det finns också en avkodning som
kodar Unicode till 32-bitars ord.
Den vanligaste avkodningen av Unicode är UTF-8 (som kodar Unicode till en sekvens av bytes). Det finns också UTF-16, UTF-16BE, UTF-16LE som använder 16-bitars ord och UTF-32 där varje tecken kodas i ett 32-bitars ord.
De olika kodningarna i 16-bitars ord är antingen big-endian eller little-endian. Du kan läsa mer om big-endian och little-endian i Wikipediartikeln om "Endianness".
Det finns också ofullständiga avkodningar, tex US-ASCII och ISO-8859-1. (Avkodningen ISO-8859-1 är även känd som Latin-1.) I ett Unix-system som jag använder ibland är ISO-8859-1 default. Apple Macintosh använder Unicode (UTF-8). Microsoft Windows har sin egen kodning som liknar ISO-8859-1.
De browsers jag har testat antar att en web-sida är kodad med ISO-8859-1 om ingen annan information finns. Detta gäller även om browsern körs under ett OS som i andra sammanhang har UTF-8 som default. Det gör att om du vill titta på en fil som är kodad i UTF-8 kan du få olika resultat beroende på om du klickar på länken som vanligt eller om du laddar ner filen genom att högerklicka.
Om du anropar javakompilatorn på kommandoraden (med kommandot javac
)
kan du ge optionen -encoding
. På så sätt kan du styra vilken kodning
kompilatorn använder. Exempel:
javac -encoding iso-8859-1 Hej.java
Jag har skrivit ett testprogram Unitest.java
. Med det kan vi undersöka
hur olika strängar lagras i olika avkodningar.
Programmet läser in en sträng och namnet på en avkodning från kommandoraden. Strängen skrivs sen till en byte-array enligt avkodningen. Byte-arrayen skrivs till standard output, i numeriskt format.
Vi tittar på avkodningar av strängen "får". Den svenska bokstaven "å" saknas i ascii och kodas olika i andra avkodningar.
$ java Unitest får us-ascii [102, 63, 114] $ java Unitest får iso-8859-1 [102, 229, 114] $ java Unitest får utf-8 [102, 195, 165, 114] $ java Unitest får utf-16 [254, 255, 0, 102, 0, 229, 0, 114] $ java Unitest får utf-16le [102, 0, 229, 0, 114, 0] $ java Unitest får utf-16be [0, 102, 0, 229, 0, 114] $ java Unitest får utf-32 [0, 0, 0, 102, 0, 0, 0, 229, 0, 0, 0, 114]
Som provkörningen visar tar strängen "får" upp 3, 4, 6, 8 eller 12 bytes beroende på avkodning.
Ascii har inget sätt att representera bokstaven "å". I stället får vi talet 63 som är ascii-koden för "?".
I iso-8859 (latin-1) kodas alla tecken med en byte och bokstaven "å" får koden 229. (Ascii använder bara koderna upp till 127.)
Utf-8 använder två bytes för att koda "å" men en byte för "f" och "r".
Utf-16, utf-16le och utf-16be kodar bokstäver i ord om två bytes (16 bitar). Varje bokstav i strängen "får" kan kodas i 16 bitar (men det finns tecken i Unicode som använder två ord om sammanlagt fyra bytes).
Utf-32 använder fyra bytes (32 bitar) per tecken. Även här får bokstaven "å" koden 229. Kodningen är big-endian, vilket innebär att koden 229 i sin tur representeras med tre bytes innehållande 0 följt av en byte med värdet 229.