Teckenuppsättningar och Servlets/JSP
När tecken som inte ingår i 7-bits ASCII (tex å, ä,
ö, Å, Ä eller Ö) ska hanteras riskerar vi problem
med teckenuppsättningarna. Det viktiga är att alla browsrar använder
samma teckenuppsättning som servern. Den här sidan avhandlar bara
kodning av tecken som sänds från browsern till servern, tex genom
att användaren fyller i ett HTML-formulär.
På servern
Det är förmodligen ingen bra ide att anpassa servern eftersom
vi inte kan lita på att alla browsrar beter sig lika. Väljer vi
ändå att göra det finns det två olika sätt:
- Klassen javax.servlet.ServletRequest (som är superklass
till javax.servlet.http.HttpServletRequest) innehåller metoden
setCharacterEncoding(java.lang.String env)
som kan
användas för att ange vilket teckenset som ska användas när
requestparametrar läses. Den metoden måste anropas innan något
läses. Om setCharacterEncoding(java.lang.String env)
inte anropas och HTTP-requestet inte innehåller någon uppgift
om teckenset i headern Content-type ska servern, enligt Servlet-specifikationen
2.3 (051122:gäller även 2.4), anvvända ISO-8859-1 och getCharacterEncoding(java.lang.String env)
ska returnera null.
- Förmodligen finns det något serverspecifikt sätt
att ange att en annan teckenuppsättning än ISO-8859-1
(se ovan) ska vara default.
I browsern
Enligt HTML 4.0 kan attributet accept-charset användas för
att tala om för browsern vilket teckenset som ska användas för
att skicka tecken från ett visst formulär, se specifikationen.
Om detta attribut saknas rekommenderar specifikationen att browsern använder
samma teckenuppsättning som servern använde när den skickade
HTML-sidan med formuläret, men det är inget krav.
Några mycket korta ord om teckenuppsättningar
ISO/IEC har tagit fram standarden 10646 som brukar kallas UCS (Universal
Character Set) och ska innehålla alla världens tecken.
UCS-2 har 16-bitars tecken och UCS-4 har 32-bitars. Unicode är
en teckenuppsättning framtagen av en sammanslutning av olika företag.
Från version 1.1 är Unicode kompatibel med ISO/IEC 10646. Exakt
vad kompatibel betyder i det här fallet är inte solklart,
men vad gäller svenska bokstäver (inklusive åäöÅÄÖ)
är det ingen skillnad på Unicode och UCS-2. Unicode-tecken är
16 bitar långa.
US-ASCII eller (7-bits ASCII) är en "mycket gammal" teckenuppsättning
som (hör och häpna) har 7-bitars tecken. Den innehåller bla
alla svenska bokstäver utom åäöÅÄÖ. ISO
8859-1 (eller ISO Latin-1) är en teckenuppsättning
som har 8-bitars tecken. Den innehåller även å, ä, ö,
Å, Ä och Ö Alla teckenkoder upp till 127 är identiska
med US-ASCII. De "första" 256 tecknen i Unicode/UCS-2 består av
åtta nollor följt av teckenkoden i ISO 8859-1.
UTF-8 (UCS Transformation Format) är ingen
teckenuppsättning utan en transformation av Unicode/UCS-2. Poängen
med den är att kunna spara tecken från Unicode/UCS-2 utan att det
ska finnas några byte som är otillåtna enligt reglerna för
vedertagna filsystem. Alla tecken i US-ASCII har exakt samma kod i UTF-8,
vilket däremot inte gäller för övriga tecken i
ISO 8859-1. Om tex 'å' sparas med UTF-8 och läses med ISO 8859-1
blir resultatet 'Ã¥'. Om 'å' sparas med ISO 8859-1 och läses
med UTF-8 blir resultatet en otillåten kod (vilket visas lite hur som
helst). UTF-16 är en transformation från UCS-4 till UCS-2
som saknar betydelse för svenska tecken.
HTTP tillåter endast ett subsett av tecknen i US-ASCII att skickas
i klartext. Övriga tecken ska skickas på formatet %HH där
HH är tecknets kod i hexadecimal form. Tyvärr anger inte http vilken
standard som ska användas för tecknets kod. Många browsrar
använder för närvarnade (031027) ISO 8859-1 för de svenska
bokstäverna.
Några ord om Tomcat 5.5
Om Tomcat används gäller inte det som står i stycket nedan. Tomcat följer servlet-specen (förstås,
den är ju specen) och tolkar alltså post-parametrar enligt ISO-8859-1 default.
Några ord om Orion 2.0.2
Jag råkade använda Orion 2.0.2 när jag gjorde ovanstående
utforskning, så jag skriver ned några speciella iaktagelser just
för den servern. Om inte attributet default-charset används
i taggen orion-web-app i orion-web.xml kommer orion att
använda UTF-8 för att läsa request-parametrar oavsett om setCharacterEncoding(
"ISO-8859-1")
anropats eller ej. Om däremot default-charset angetts till
iso-8859-1 kommer orion att använda ISO 8859-1 om
setCharacterEncoding
inte anropats. Anropas setCharacterEncoding(
"ISO-8859-1")
går orion över till UTF-8.
Orion förljer alltså inte servlet-specen.