Kāds no http://journal.bad.lv lietotājiem mani palūdza izskaidrot atšķirību starp UTF-8, UTF-16 un Unicodi. Šeit arī skaidrojums, kas varētu noderēt ne tikai viņam.
Reiz kaut kad sen Laacz bija iemetis linku uz jauku rakstu par Unicodi – to var lasīt Joel Spolsky rakstā. Bet ja nu gadījumā nav laika lasīt angliskus tekstus, šeit neliels satura atstāstījums.
Būtībā Unicode ir tikai standarts, kas definē abstraktu kodējumu valodas simboliem, katram simbolam piekārtojot savu kodu. Unicode pasaka, ka “a” == “U+0061”, “ā”=”U+0101” un tamlīdzīgi, bet nav runas par to, kā to nokodēt bitu virknēs.
UTF-16 ir tieša Unicode implementācija – ja ir pateikts, ka a=U0061, tad a kodējam to ar 16 bitiem, tas ir, diviem baitiem – 00 un 61, kas atbilst 003D heksadecimālajā sistēmā.
Unicode apzīmējumus var apskatīt programmā Character Map (Start->Programs->Accessories->System tools->Character map). Tur arī var pamanīt, ka visiem “normālajiem” Ascii burtiem pirmais baits ir vienmēr 00, bet, piemēram, latviešu simboliem pirmajam baitam ir nenulles vērtība (01).
Nez kāpēc amerikāņu un angļu programmētājiem sāka šķist, ka Unicode pamatīga liekvārdība — kāpēc gan viņiem starp katriem diviem baitiem būtu jāraksta 00???? – jo tiešām, viņiem Unicode ne ar ko citu neatšķiras no ASCII.
Tāpēc tika izdomāts UTF-8 kodējums, kuram, ja pirmais baits ir 00, tas tiek izlaists. Līdz ar to priekš “plain ASCII” valodām kā angļu (vai …. hmmm, vai ir vēl kāda?) UTF-8 ir praktiski vienbaitīgs. Toties tekstos, kuri satur arī reģionālos kodējumos nepieciešamos burtus, ik pa brīdim būs “vairāk nekā vienbaitīgi” simboli, tas ir, piemēram, latviešu burtu apzīmēšanai tiek lietoti vismaz divi baiti.
Patiesībā gan UTF-8 rada daudz problēmu. Piemēram, par journal.bad.lv aptaujām zināms, ka atbildes garums drīkst būt ne vairāk kā 255 simboli. Tomēr patiesībā ar to ir domāti 255 baiti, nevis simboli. Tātad, ja tu raksti ar latviešu burtiem, daži no tiem aizņems nevis vienu, bet vairākus baitus, līdz ar to kopējais teksta garums būs mazāks nekā 255 simboli.
Līdzīgi arī problēmas rodas ar tādu vienkāršu uzdevumu kā teksta garuma noskaidrošana – līdz šim varēja paskatīties, cik vietas atmiņā aizņem string tipa mainīgais, tagad ir katru reizi jāpārbauda, vai tajā gadījumā nav vairākbaitīgu simbolu. Arī string tipa vērtību sakārtošana augošā vai dilstošā secībā kļuvusi sarežģītāka – atmiņas apgabalā var būt biti, kas nav jāievēro, salīdzinot divus mainīgos.
Patiesībā priekš mums ērtāks būtu UTF-16 kodējums – salīdzināšana darbotos, garuma noteikšanas funkcijas darbotos, tikai rezultāts būtu jādala ar 2. Vienīgā problēma – tas aizņem tieši divreiz vairāk diska vietas, divreiz vairāk atmiņas un rada divreiz lielāku datu plūsmu, kad nepieciešams pārsūtīt informāciju.
Paldies sm par papildinājumu: UTF-8 var būt vienbaitīgs, bet var arī aizņemt līdz pat sešiem baitiem uz simbolu
6 thoughts on “Unicode: UTF-8, UTF-16 un citi”
Comments are closed.
Eh es te pamazam censos parvakties no iestivejusa windows-1257 uz utf-8, lai ari linuxisti un mac-isti varetu lasit manu “apmeklejuma bagato” (:D) lapeli, bet te nu bija – shitada klapata. Vel jau tur visi tie UTF-32 (big endian, little endian – kas tie pa zveriem?)
Nezin .. shitas jokas ar simbola garumu baitos attiecas tikai uz filesize() tipa funkcijam, jeb ari strlen()? (tas ieks php)
Šī problēma neattiecas uz funkcijām, kas darbojas ar datiem kā “baitu čupiņu”, piemēram, filesize()- tai ir vienalga, kas par datiem iekšā failā, saskaitām baitus un viss. Toties funkcijas, kas strādā ar string tipa datiem, darbojas korekti tikai tad, ja tās ņem vērā, cik baitu aizņem katrs simbols. Piemēram, tā pati substr() funkcija PHP var pārgriezt UTF-8 burtu “uz pusēm”, jo tā ignorē daudzbaitīgos kodējumus. Var palasīt šeit: http://laacz.lv/blog/2004/05/27/multibytestringfunctions
gusc: Kopš kura laika linuxistiem ir problēmas ar lapām Windows-1257 (ISO-8859-13) kodējumā? Linux Opera un Linux Firefox uztur tieši tos pašus kodējumus, ko Windows Opera un Windows Firefox.
nez, man likās ka bija gan kaukādi čakari, nu moš ne jau ar diezgan advancētajiem linuxiem, bet cik atceros uz solaris 9 (ar defaulto Netscapi – well, kurš gan to vēl lieto :D) un uz MacOS (ar Safari kaukādu 1.0 versiju uz MacOS X Panther) gan bij tā ka LV burti vienkārši bija standarta latin alfabēta burti (nu tie ar nepareizajām garumzīmēm).
Paskatījos uz Links2 iekš Gentoo Linuxa, win-1257 – bez garumzīmēm, aber utf-8 ir galigie kjeburi, bet nu tur laikam manis paša vaina – kauko neesu pieinstalējis :/
advanceetie linuxi – solaris un macos? :)