UTF8 strings and characters/fi
│
English (en) │
suomi (fi) │
русский (ru) │
UTF-8 merkit ja merkkijonot
UTF-8:n kauneus
Tavut joiden ylin bitti on '0' (0xxxxxxx) on varattu ASCII- yhteensopiville yhden tavun merkille. Monitavuisilla 1: n lukumäärä ensimmäisessä tavussa määrää koodin tavujen tavujen määrän. Esimerkit :
- 1 tavu : 0xxxxxxx
- 2 tavua : 110xxxxx 10xxxxxx
- 3 tavua : 1110xxxx 10xxxxxx 10xxxxxx
- 4 tavua : 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
Merkistökoodaus UTF-8:n suunnittelussa on joitain etuja verrattuna muihin koodauksiin:
- Se on taaksepäin yhteensopiva ASCII:n kanssa ja tuottaa pienikokoisia datatiedostoja länsimaisille kielille. ASCII:ta käytetään myös merkintäkielen tunnisteissa ja muissa metatiedoissa, jotka antavat UTF-8: lle etua millä tahansa kielellä.
Kuitenkin tämä taaksepäin yhteensopivuus ei ulotu koodiin, koska koodia on käsiteltävä niin että vältetään utf8-merkkijonoja.
- Monitavuisen datan eheys voidaan todentaa '1'-bittien määrästä kunkin tavun alussa.
- Aina löytyy monitavuisen kooditavun alkukohta, vaikka hyppättäisiin satunnaisen tavun paikkaan.
- Tavu tietyssä paikassa monitavuisessa sekvenssissä ei voi koskaan sekoittaa muiden tavujen kanssa. Tämä sallii perinteisten nopeiden merkkijono funktioiden, kuten Pos () ja Copy (), käytön monissa tilanteissa. Katso esimerkkejä alenpana.
Huomaa, että UTF-16: ssä on samanlaisia eheysominaisuuksia. (D800-alue signaalit ensin korvikkeena, DC00-alue signaalit toissijaisen korvaavan osan)
- Vakaa koodi. Koodi, joka käsittelee koodipisteitä, on aina tehtävä oikein UTF-8: n kanssa, koska monitavuiset koodipisteet ovat yleisiä. UTF-16: ssä on runsaasti "likaista" koodia, joka olettaa koodipisteiden kiinteän leveyden.
- Useimmat Internetissä olevat tekstitiedot on koodattu UTF-8: ksi. Tietojen käsittely suoraan UTF-8: ksi eliminoi hyödyttömiä muunnoksia. Useat (Unix-) käyttöjärjestelmät käyttävät UTF-8:aa natiivisti.
Esimerkit
Yksinkertainen iterointi merkkien yli ikään kuin merkkijono olisi joukko yhtä suuria elementtejä ei toimi Unikoodissa. Tämä ei ole pelkästään UTF-8: lle ominaista, Unicode-standardi on monimutkainen ja sana "merkki" on epäselvä. Jos halutaan iteroida UTF-8-merkkijonon merkkejä, on periaatteessa kaksi tapaa:
- iterointi tavujen yli - hyödyllinen alimerkkijonon etsimiseksi tai kun tarkastellaan vain UTF8-merkkijonon ASCII-merkkejä, esimerkiksi XML-tiedostojen jäsentämisessä.
- iterointi koodipisteiden tai merkkien yli - hyödyllinen graafisille komponenteille kuten SynEdit, esimerkiksi kun halutaan tietää kolmannen tulostettavan merkin näytöllä.
Alimerkkijonon etsiminen
UTF8: n erityisluonteen vuoksi voit yksinkertaisesti käyttää tavanomaisia merkkijonofunktioita alimerkkijonon etsimiseen. Kelvollisen UTF-8-merkkijonon etsiminen Pos: lla palauttaa aina oikean UTF-8 tavun paikan:
uses LazUTF8;
...
procedure Where(SearchFor, aText: string);
var
BytePos: LongInt;
CodepointPos: LongInt;
begin
BytePos:=Pos(SearchFor,aText);
CodepointPos:=UTF8Pos(SearchFor,aText);
writeln('The substring "',SearchFor,'" is in the text "',aText,'"',
' at byte position ',BytePos,' and at codepoint position ',CodepointPos);
end;
Etsi ja kopioi
Toinen esimerkki siitä, miten Pos (), Copy () ja Length () toimivat UTF-8: n kanssa. Tällä toiminnolla ei ole koodia käsitellä UTF-8-koodausta, mutta se toimii aina voimassa olevan UTF-8-tekstin kanssa.
function SplitInHalf(Txt, Separator: string; out Half1, Half2: string): Boolean;
var
i: Integer;
begin
i := Pos(Separator, Txt);
Result := i > 0;
if Result then
begin
Half1 := Copy(Txt, 1, i-1);
Half2 := Copy(Txt, i+Length(Separator), Length(Txt));
end;
end;
Iterointi merkkijonon yli etsien ASCII merkkejä
Jos halutaan vain etsiä merkkejä ASCII-alueella, voidaan käyttää Char-tyyppiä ja verrata Txt[i] -muotoon aivan kuten aiemmin tehtiin. Useimmat jäsentimet tekevät niin ja ne toimivat yhä.
procedure ParseAscii(Txt: string);
var
i: Integer;
begin
for i:=1 to Length(Txt) do
case Txt[i] of
'(': PushOpenBracketPos(i);
')': HandleBracketText(i);
end;
end;
Iterointi merkkijonon yli etsien Unikoodi merkkejä tai tekstiä
Jos halutaan löytää merkkijonossa kaikki tietyn merkin tai alimerkkijonon esiintymät niin kutsutaan PosEx()-funktiota toistuvasti.
Jos halutaan testata eri tekstiä silmukan sisällä, voidaan silti käyttää nopeata Copy() ja Length() funktiota. UTF-8-ominaisuuksia voitaisiin käyttää, mutta niitä ei tarvita.
procedure ParseUnicode(Txt: string);
var
Ch1, Ch2, Ch3: String;
i: Integer;
begin
Ch1 := 'Й'; // Characters to search for. They can also
Ch2 := 'ﯚ'; // be combined codepoints or longer text.
Ch3 := 'Å';
for i:=1 to Length(Txt) do
begin
if Copy(Txt, i, Length(Ch1)) = Ch1 then
DoCh1(...)
else if Copy(Txt, i, Length(Ch2)) = Ch2 then
DoCh2(...)
else if Copy(Txt, i, Length(Ch3)) = Ch3 then
DoCh3(...)
end;
end;
Silmukkaa voidaan optimoida hyppäämällä jo käsiteltävien osien päälle.
Merkkijonon yli iterointi analysoimalla yksittäisiä koodipisteitä
Tämä koodi kopioi kunkin koodipisteen String-tyyppiseen muuttujaan, jota voidaan sitten käsitellä edelleen.
procedure IterateUTF8(S: String);
var
CurP, EndP: PChar;
Len: Integer;
ACodePoint: String;
begin
CurP := PChar(S); // if S='' then PChar(S) returns a pointer to #0
EndP := CurP + length(S);
while CurP < EndP do
begin
Len := UTF8CodepointSize(CurP);
SetLength(ACodePoint, Len);
Move(CurP^, ACodePoint[1], Len);
// A single codepoint is copied from the string. Do your thing with it.
ShowMessageFmt('CodePoint=%s, Len=%d', [ACodePoint, Len]);
// ...
inc(CurP, Len);
end;
end;
Tavujen käyttäminen yhdellä UTF8-koodipisteellä
UTF-8-koodatut koodipisteet voivat vaihdella pituudeltaan, joten paras ratkaisu niiden käyttämiseen on käyttää iteraatiota. Voidaan iteroida koodeja käyttämällä tätä koodia:
uses LazUTF8;
...
procedure DoSomethingWithString(AnUTF8String: string);
var
p: PChar;
CPLen: integer;
FirstByte, SecondByte, ThirdByte, FourthByte: Char;
begin
p:=PChar(AnUTF8String);
repeat
CPLen := UTF8CodepointSize(p);
// Here you have a pointer to the char and its length
// You can access the bytes of the UTF-8 Char like this:
if CPLen >= 1 then FirstByte := P[0];
if CPLen >= 2 then SecondByte := P[1];
if CPLen >= 3 then ThirdByte := P[2];
if CPLen = 4 then FourthByte := P[3];
inc(p,CPLen);
until (CPLen=0) or (p^ = #0);
end;
Pääsy N:teen UTF8-koodipisteeseen
Iteraation lisäksi voi olla myös halu päästä satunnaiseen UTF-8-koodipisteeseen.
uses LazUTF8;
...
var
AnUTF8String, NthCodepoint: string;
begin
NthCodepoint := UTF8Copy(AnUTF8String, N, 1);
Näytetään koodipisteet UTF8CodepointToUnicode-ohjelmalla
Seuraavassa on esimerkki siitä, miten kunkin koodipisteen 32 bittisen koodipisteen arvo näytetään UTF8-merkkijonona:
uses LazUTF8;
...
procedure IterateUTF8Codepoints(const AnUTF8String: string);
var
p: PChar;
unicode: Cardinal;
CPLen: integer;
begin
p:=PChar(AnUTF8String);
repeat
unicode:=UTF8CodepointToUnicode(p,CPLen);
writeln('Unicode=',unicode);
inc(p,CPLen);
until (CPLen=0) or (unicode=0);
end;
Hajotetut merkit
Unicoden epäselvyyden vuoksi vertailufunktioissa ja Pos() saattaa näkyä odottamatonta käyttäytymistä, kun esimerkiksi yksi merkkijono sisältää hajonneita merkkejä, kun taas toinen käyttää samaan kirjaimeen suoria koodeja. RTL ei käsittele sitä automaattisesti. Se ei ole mikään koodaus, mutta yleensä Unicode.
macOS
FileUtil-yksikön tiedostotoiminnot huolehtivat myös Mac OS X - käyttöjärjestelmäkohtaisesta käyttäytymisestä: OS X normalisoi tiedostonimet. Esimerkiksi filename 'ä.txt' voidaan koodata Unicodessa kahdella eri sekvenssillä (#$C3#$A4 ja 'a'#$CC#$88). Linuxissa ja BSD:ssä voidaan luoda tiedostonimi molemmilla koodauksilla. OS X muuntaa automaattisesti umlaut kolmelle tavujärjestykselle. Tämä tarkoittaa:
if Filename1 = Filename2 then ... // is not sufficient under OS X
if AnsiCompareFileName(Filename1, Filename2) = 0 then ... // not sufficient under fpc 2.2.2, not even with cwstring
if CompareFilenames(Filename1, Filename2) = 0 then ... // this always works (unit FileUtil or FileProcs