{"id":95911,"date":"2020-10-05T01:42:09","date_gmt":"2020-10-04T23:42:09","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/eshhyo-odin-velosiped-hranim-yunikodnye-stroki-na-30-60-kompaktnee-chem-utf-8"},"modified":"2020-10-05T01:42:09","modified_gmt":"2020-10-04T23:42:09","slug":"eshhyo-odin-velosiped-hranim-yunikodnye-stroki-na-30-60-kompaktnee-chem-utf-8","status":"publish","type":"post","link":"https:\/\/prohoster.info\/et\/blog\/administrirovanie\/eshhyo-odin-velosiped-hranim-yunikodnye-stroki-na-30-60-kompaktnee-chem-utf-8","title":{"rendered":"Veel \u00fcks jalgratas: salvestame Unicode'i stringid 30-60% kompaktsemalt kui UTF-8","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Veel \u00fcks jalgratas: salvestame Unicode&#039;i stringid 30-60% kompaktsemalt kui UTF-8\" src=\"\/wp-content\/uploads\/2020\/10\/56c10bad377127b711bdb204ee300772.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nKui olete arendaja ja silmitsi valikuga kodeeringu osas, siis peaaegu alati on \u00f5ige lahendus Unicode. Konkreetne esitamise meetod s\u00f5ltub kontekstist, kuid enamasti on siin samuti universaalne vastus \u2014 UTF-8. See on hea seet\u00f5ttu, et v\u00f5imaldab kasutada k\u00f5iki Unicode'i m\u00e4rke, kulutamata <em>liialt<\/em> palju baite enamikul juhtudel. T\u00f5si, keelte puhul, mis ei kasuta ainult ladina t\u00e4hestikku, t\u00e4hendab \u201eliialt v\u00e4he\u201d v\u00e4hemalt <strong>kaht byte'i s\u00fcmboli kohta<\/strong>. Kas on v\u00f5imalik paremini, naasmata eelajaloolistesse kodeeringutesse, mis piiravad meid vaid 256 saadaval s\u00fcmboliga?<\/p>\n<p>Allpool pakun v\u00e4lja oma katse anda sellele k\u00fcsimusele vastus ja teostada suhteliselt lihtne algoritm, mis v\u00f5imaldab salvestada ridu enamikus maailma keeltes, lisamata neid \u00fcleliigseid koormusi, mis on omased UTF-8-le.<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p><i>\u00c4ratus.<\/i> T\u00f5in esile mitmeid olulisi juhtn\u00f6\u00f6re: <strong>kirjeldatud lahendust ei pakuta universaalse asendusena UTF-8-le<\/strong>, see sobib vaid kitsas nimekirjas juhtudest (millest kirjutan allpool), ja seda ei tohi mingil juhul kasutada kolmandate osapoolte API-dega suhtlemiseks (kes sellest isegi ei tea). Enamasti sobivad suure hulga tekstiliste andmete kompaktseks hoidmiseks \u00fcldotstarbelised tihendamisalgoritmid (n\u00e4iteks deflate). Lisaks leidsin juba oma lahenduse loomise k\u00e4igus olemasoleva standardi ise Unicode'is, mis lahendab sama \u00fclesande \u2014 see on veidi keerulisem (ja tihti kehvem), kuid siiski vastuv\u00f5etud standard, mitte jalgaastatud lahendus. Kannan ka sellest teada.<\/p>\n<h2>Unicode ja UTF-8<\/h2>\n<p>\nAlustuseks \u2014 paar s\u00f5na sellest, mis see \u00fcldiselt on <strong>Unicode<\/strong> ja <strong>UTF-8<\/strong>.<\/p>\n<p>Kuidas on teada, olid varem populaarsed 8-bitised kodeeringud. Nendega oli k\u00f5ik lihtne: 256 s\u00fcmbolit saab nummerdada numbritega vahemikus 0 kuni 255, ning numbrid vahemikus 0 kuni 255 on selgelt esitatavad \u00fche baidina. Kui minna tagasi algusesse, siis ASCII kodeering piirneb isegi 7 bitiga, seega on selle baidiesituses k\u00f5ige vanem bit null, ja enamik 8-bitisi kodeeringuid on sellega \u00fchilduvad (need erinevad ainult \u201e\u00fclemises\u201d osas, kus vanem bit on \u00fcks).<\/p>\n<p>Kuidas eristub Unicode neist kodeeringutest ja miks on sellega seotud korraga mitmed konkreetsed esitused \u2014 UTF-8, UTF-16 (BE ja LE), UTF-32? Selgitame j\u00e4rjest.<\/p>\n<p>Peamine Unicode'i standard kirjeldab ainult vastavust t\u00e4hem\u00e4rkide (ja m\u00f5nel juhul - t\u00e4hem\u00e4rkide eraldi komponentide) ja nende numbrite vahel. Ja v\u00f5imalikke numbreid selles standardis on v\u00e4ga palju - alates <code><b>0x00<\/b><\/code> kuni <code><b>0x10FFFF<\/b><\/code> (1 114 112 t\u00fckki). Kui me tahaksime sellises vahemikus arvu muutuja sisse panna, ei piisaks meile ei 1 ega 2 baitist. Ja kuna meie protsessorid ei ole kolmbaitsete arvudega v\u00e4ga harjutanud, oleksime sunnitud kasutama terveid 4 baiti \u00fche t\u00e4hem\u00e4rgi jaoks! Just see ongi UTF-32, kuid just selle \"rahakulu\" t\u00f5ttu ei ole see formaat populaarne.<\/p>\n<p>\u00d5nneks ei ole Unicode'i t\u00e4hem\u00e4rgid korduvad juhuslikult. Nende suur hulk on jaotatud 17 \u00ab<em>tasandisse<\/em>\u00bb, millest iga\u00fcks sisaldab 65536 (<code><b>0x10000<\/b><\/code>) \u00ab<em>koodipunkti<\/em>\u00bb. M\u00f5isted \u201ekoodipunkt\u201d t\u00e4histab siin lihtsalt <em>t\u00e4hem\u00e4rgi numbrit<\/em>, mille Unicode on talle m\u00e4\u00e4ranud. Kuid nagu eespool mainitud, on Unicode'is nummerdatud mitte ainult eraldi t\u00e4hem\u00e4rgid, vaid ka nende komponendid ja teenindusm\u00e4rkmed (ja m\u00f5nikord ei vasta number \u00fcldse millelegi - v\u00f5ib-olla ajutiselt, kuid meile pole see niiv\u00f5rd oluline), seega on korrektsem alati r\u00e4\u00e4kida just numbrite koguarvust, mitte t\u00e4hem\u00e4rkidest. Siiski, edaspidigi kasutan sageli s\u00f5na \u201et\u00e4hem\u00e4rk\u201d, silmas pidades m\u00f5istet \u201ekoodipunkt\u201d.<\/p>\n<p><img decoding=\"async\" alt=\"Veel \u00fcks jalgratas: salvestame Unicode&#039;i stringid 30-60% kompaktsemalt kui UTF-8\" src=\"\/wp-content\/uploads\/2020\/10\/7ad84b571a8025582fdbc3db956cb3b0.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Unicode'i tasandid. Nagu n\u00e4ha, on suur osa (tasandid 4 kuni 13) endiselt kasutamata.<\/i><\/p>\n<p>Mis k\u00f5ige t\u00e4helepanuv\u00e4\u00e4rsem on see, et kogu peamine \"sisu\" asub nulltasemel, seda nimetatakse \"<em>Basic Multilingual Plane<\/em>\". Kui rida sisaldab teksti \u00fches kaasaegses keeles (sealhulgas hiina keeles), ei saa te sellest tasemest v\u00e4lja minna. Kuid ka \u00fclej\u00e4\u00e4nud Unicode'i osa ei tohi eemaldada \u2014 n\u00e4iteks emoji'd asuvad peamiselt j\u00e4rgmise taseme l\u00f5pupoole \"<em>Supplementary Multilingual Plane<\/em>\" (see ulatub alates <code><b>0x10000<\/b><\/code> kuni <code><b>0x1FFFF<\/b><\/code>). Seet\u00f5ttu k\u00e4itub UTF-16 nii: k\u00f5ik t\u00e4hem\u00e4rgid, mis j\u00e4\u00e4vad <em>Basic Multilingual Plane<\/em>, kodeeritakse \u201enagu on\u201d, nende vastav kahekohaline number. Kuid osa numbritest selles vahemikus ei t\u00e4hista \u00fcldse konkreetseid t\u00e4hem\u00e4rke, vaid osutavad sellele, et p\u00e4rast seda kaht baidi paari tuleb vaadata veel \u00fchte - kombineerides nende nelja baidi v\u00e4\u00e4rtused, saame numbri, mis katab kogu lubatud Unicode'i vahemiku. Seda esitusviisi nimetatakse \u201esuurte paarideks\u201d - v\u00f5ib-olla olete neist kuulnud.<\/p>\n<p>Seega, UTF-16 n\u00f5uab \u00fche \"koodipunkti\" jaoks kahte v\u00f5i (v\u00e4ga harvadel juhtudel) neli baiti. See on parem kui pidev nelja baitide kasutamine, kuid ladina t\u00e4hestiku (ja teiste ASCII-m\u00e4rkide) puhul kulutab see sellise kodeerimisega pool salvestatud ruumist nullidele. UTF-8 on loodud seda parandama: ASCII v\u00f5tab seal nagu varem ainult \u00fche bait; koodid alates <code><b>0x80<\/b><\/code> kuni <code><b>0x7FF<\/b><\/code> \u2014 kahest baitist; alates <code><b>0x800<\/b><\/code> kuni <code><b>0xFFFF<\/b><\/code> \u2014 kolmest ja alates <code><b>0x10000<\/b><\/code> kuni <code><b>0x10FFFF<\/b><\/code> \u2014 neljast. \u00dchelt poolt on ladina t\u00e4hestikul n\u00fc\u00fcd h\u00e4sti: tagasiviidatud \u00fchildus ASCII-ga, ning jaotus on \u00fchtlasemalt \"jaotatud\" 1 kuni 4 baidi vahel. Kuid ladina t\u00e4hestikust erinevad t\u00e4hestikud, kahjuks, ei saa UTF-16-ga v\u00f5rreldes midagi v\u00f5ita, ja paljud n\u00f5uavad n\u00fc\u00fcd kolmandat bait; kahe baitiga kirje katab vahemiku 32 korda v\u00e4henenud, ulatudes <code><b>0xFFFF<\/b><\/code> kuni <code><b>0x7FF<\/b><\/code>, ja see ei h\u00f5lma enam hiina keelt ega n\u00e4iteks gruusi keelt. Kirillitsa ja veel viiele t\u00e4hestikule \u2014 uh-huh \u2014 vedas, 2 baiti s\u00fcmboli kohta.<\/p>\n<p>Kuidas see siis v\u00e4lja tuleb? Vaatame, kuidas UTF-8 esindab s\u00fcmbolite koode:<br \/>\n<img decoding=\"async\" alt=\"Veel \u00fcks jalgratas: salvestame Unicode&#039;i stringid 30-60% kompaktsemalt kui UTF-8\" src=\"\/wp-content\/uploads\/2020\/10\/4ef4fe9e949cd75295c45c053dbca6d3.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nNumbrite otseseks esitamiseks on siin kasutatud bitte, t\u00e4histatud s\u00fcmboliga <code><b>x<\/b><\/code>. On n\u00e4ha, et kahe baitiga kirjes on selliseid bitte vaid 11 (16-st). Esialgsed bitid kannavad siin ainult teeninduslikku funktsiooni. Nelja baitiga kirje puhul on koodipunkti number m\u00e4\u00e4ratud t\u00e4ielikult 21 bitile 32-st \u2013 n\u00e4iliselt peaks siin piisama kolmest baitist (mis annab kokku 24 bitti), kuid teenindusm\u00e4rgid v\u00f5tavad liiga palju ruumi.<\/p>\n<p>Kas see on halb? Tegelikult mitte. \u00dchelt poolt \u2013 kui me hoolime v\u00e4ga salvestusruumist, on meil olemas tihendamisalgoritmid, mis k\u00f5rvaldavad kergesti kogu liigse entropia ja \u00fcleliigsuse. Teiselt poolt \u2013 Unicode eesm\u00e4rk oli anda v\u00f5imalikult universaalne kodeerimine. N\u00e4iteks v\u00f5ime UTF-8-s kodeeritud stringi usaldada koodile, mis t\u00f6\u00f6tas varem ainult ASCII-ga, ja ei muretse, et seal n\u00e4eb s\u00fcmbolit ASCII vahemikust, mida seal tegelikult ei ole (sest UTF-8-s on k\u00f5ik baitid, mis algavad nullbitiga \u2013 need ongi ASCII). Ja kui me tahame \u00e4kki suurt stringist m\u00f5ne v\u00e4ikese saba \u00e4ra l\u00f5igata, ilma et me seda algusest peale dekodeeriksime (v\u00f5i taastaksime teavet p\u00e4rast kahjustatud osa) \u2013 ei ole meil keeruline leida seda nihke kohta, kust m\u00f5ni s\u00fcmbol algab (piisab, kui m\u00f6\u00f6da minna baitsidest, millel on bittide eellane <code><b>10<\/b><\/code>).<\/p>\n<h2>Miks siis midagi uut v\u00e4lja m\u00f5elda?<\/h2>\n<p>\nSamas ajal esineb harva olukordi, kus kokkusurumisalgoritmid nagu deflate ei ole h\u00e4sti rakendatavad, kuid soov on saavutada kompaktsed stringide salvestamise vormid. Isiklikult olen sellise \u00fclesande ees seisnud, kui olen m\u00f5elnud <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Radix_tree\">kokkusurutud prefikspuu<\/a><\/noindex> suure s\u00f5navara jaoks, mis sisaldab s\u00f5nu erinevates keeltes. \u00dchelt poolt on iga s\u00f5na v\u00e4ga l\u00fchike, seega on selle kokkusurumine ebaefektiivne. Teiselt poolt - puu realiseerimine, millele ma m\u00f5tlesin, eeldas, et iga salvestatud stringi bait genereeris eraldi puu tipu, mist\u00f5ttu oli nende arvu v\u00e4hendamine v\u00e4ga kasulik. Minu teegis <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/deNULL\/Az.js\">Az.js<\/a><\/noindex> (nagu ka <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/kmike\/pymorphy2\">pymorphy2<\/a><\/noindex>, millele see p\u00f5hineb) selline probleem lahendatakse lihtsalt - stringid, mis on pakitud <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Deterministic_acyclic_finite_state_automaton\">DAWG<\/a><\/noindex>-s\u00f5naraam, s\u00e4ilitatakse seal <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/deNULL\/Az.js\/blob\/master\/src\/az.dawg.js\">vana hea CP1251<\/a><\/noindex>. Kuid nagu on lihtne m\u00f5ista, t\u00f6\u00f6tab see h\u00e4sti ainult piiratud t\u00e4hestikuga - hiina stringi sellesse s\u00f5naraamatusse ei saa juba paigutada.<\/p>\n<p>Eraldi m\u00e4rgin veel \u00fche ebameeldiva n\u00fcansi, mis tekib UTF-8 kasutamisel sellises andmestruktuuris. \u00dclaltoodud pildilt on n\u00e4ha, et kui s\u00fcmbolit salvestatakse kahe baitina, siis selle numbri bitid ei paikne j\u00e4rjestikku, vaid on katkenud paari bitti <code><b>10<\/b><\/code> vahepeal: <code><b>110xxxxx 10xxxxxx<\/b><\/code>. Selle t\u00f5ttu, kui s\u00fcmboli koodis \u00fcletatakse teise baidi madalamad 6 bitti (st toimub \u00fcleminek <code><b>10111111<\/b><\/code> \u2192 <code><b>10000000<\/b><\/code>), muutub ka esimene bait. Tulemuseks on, et t\u00e4ht \u201e\u043f\u201d t\u00e4histatakse baitidega <code><b>0xD0 0xBF<\/b><\/code>, ja j\u00e4rgmine \u201e\u0440\u201d juba <code><b>0xD1&nbsp;0x80<\/b><\/code>. Prefikspuus p\u00f5hjustab see vanema tipu jagunemise kaheks - \u00fcheks prefiksi <code><b>0xD0<\/b><\/code>, ja teiseks <code><b>0xD1<\/b><\/code> (kuigi kogu kirillitsa v\u00f5iks kodeerida ainult teise baidi kaudu).<\/p>\n<h2>Mida ma sain<\/h2>\n<p>\nSelle \u00fclesande ees seistes otsustasin natuke m\u00e4ngida bittidega ja samal ajal tutvuda paremini Unicode'i struktuuriga. Tulemuseks sai koodimisformaat UTF-C (\u201eC\u201d t\u00e4histab <em>compact<\/em>), mis kulutab \u00fche koodipunkti jaoks mitte \u00fcle 3 baidi ning sageli v\u00f5imaldab kulutada vaid <strong>\u00fche lisabait terve kodeeritud stringi peale.<\/strong>See toob kaasa selle, et paljude mitte-ASCII t\u00e4hestike korral osutub selline kodeering <strong>30-60% kompaktselt kui UTF-8.<\/strong>.<\/p>\n<p>Olen vormistatud koodimise ja dekodeerimise algoritmide n\u00e4idised <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/deNULL\/utf-c\">teekidena JavaScriptis ja Go-s.<\/a><\/noindex>, v\u00f5ite neid oma koodis vabalt kasutada. Kuid tahaksin siiski r\u00f5hutada, et teataval m\u00e4\u00e4ral j\u00e4\u00e4b see formaat \u201ejalgrattaks\u201d ja ma ei soovita seda kasutada <strong>ilmse arusaamata, miks see teile vajalik on<\/strong>. See on siiski pigem eksperiment kui t\u00f5sine \u201eUTF-8 t\u00e4iustamine\u201d. Sellegipoolest on sealne kood kirjutatud korralikult, kompaktsetena, koos rohkete kommentaaride ja katsetega.<\/p>\n<p><img decoding=\"async\" alt=\"Veel \u00fcks jalgratas: salvestame Unicode&#039;i stringid 30-60% kompaktsemalt kui UTF-8\" src=\"\/wp-content\/uploads\/2020\/10\/e31978174449cd7de5d8371aaeb9ab2e.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Testide tulemused ja v\u00f5rdlus UTF-8-ga<\/i><\/p>\n<p>Lisaks tegin ma <noindex><a rel=\"nofollow\" href=\"https:\/\/denull.github.io\/utf-c\/\">demonstreerimise lehe<\/a><\/noindex>, kus saab hinnata algoritmi t\u00f6\u00f6d, ja hiljem r\u00e4\u00e4gin selle p\u00f5him\u00f5tetest ja v\u00e4ljat\u00f6\u00f6tamisprotsessist \u00fcksikasjalikumalt.<\/p>\n<h2>Eemaldame \u00fcleliigsed bitid<\/h2>\n<p>\nAluseks v\u00f5tsin loomulikult UTF-8. Esimene ja ilmselge asi, mida seal muuta saab \u2014 v\u00e4hendada teenindusbitide arvu igas baitis. N\u00e4iteks hakkab esimene bait UTF-8-s alati kas <code><b>0<\/b><\/code>, v\u00f5i <code><b>11<\/b><\/code> \u2014 ja prefiks <code><b>10<\/b><\/code> on ainult j\u00e4rgnevate baitide jaoks. Asendame prefiksi <code><b>11<\/b><\/code> . Tundub, et <code><b>1<\/b><\/code>, ja j\u00e4rgmiste baitide puhul eemaldame prefiksid t\u00e4ielikult. Mis juhtub?<\/p>\n<p><code><b>0xxxxxxx<\/b><\/code> \u2014 1 bait <br \/>\n<code><b>10xxxxxx xxxxxxxx<\/b><\/code> \u2014 2 baiti <br \/>\n<code><b>110xxxxx xxxxxxxx xxxxxxxx<\/b><\/code> \u2014 3 baiti<\/p>\n<p>Peatus, aga kus on nelja-baitline kirje? See pole enam vajalik \u2014 kolme baitiga kirjutamisel on meil n\u00fc\u00fcd 21 bitti ja seda piisab kuni <code><b>0x10FFFF<\/b><\/code>.<\/p>\n<p>Mida me siin ohverdasime? Peamine \u2014 s\u00fcmbolite piiride avastamine juhuslikust buffri kohast. Me ei saa torkida juhuslikku baidi ja leida sealt j\u00e4rgmise s\u00fcmboli algust. See on meie formaadi piirang, kuid praktikas ei esine sellist vajadust tihti. \u00dcldiselt saame p\u00fcsida buffri algusest alates (eriti kui on tegemist l\u00fchikeste ridadega).<\/p>\n<p>Kaks baitide katvuse olukord on ka paranenud: n\u00fc\u00fcd annab kaheettev\u00f5tmise formaat 14 bitist vahemiku, mis katab koodid kuni <code><b>0x3FFF<\/b><\/code>. Hiinlastel ei vea (nende ideogrammid asuvad peamiselt vahemikus <code><b>0x4E00<\/b><\/code> kuni <code><b>0x9FFF<\/b><\/code>), kuid gruusia rahvas ja paljud teised on n\u00fc\u00fcd \u00f5nnelikumad \u2014 nende keeled mahuvad samuti 2 baiti s\u00fcmboli kohta.<\/p>\n<h2>Sissev\u00f5ttes oleme dekooder<\/h2>\n<p>\nN\u00fc\u00fcd m\u00f5tleme ridade omadustele. S\u00f5naraamatus on sageli s\u00f5nad, mis on kirjutatud \u00fche t\u00e4htede alfabeediga, ja paljude teiste tekstide puhul on see samuti t\u00f5si. Oleks hea korra n\u00e4idata see alfabet, ja seej\u00e4rel n\u00e4idata ainult t\u00e4htede numbrit selle sees. Vaadakem, kas Unicode'i tabelis olevad s\u00fcmbolite asukohad aitavad meid.<\/p>\n<p>Nagu \u00fclalpool mainitud, on Unicode jagatud <em>tasanditeks<\/em> koodide iga 65536. Kuid see ei ole eriti kasulik jaotus (nagu juba mainitud, oleme enamasti nulltasemel). Huvi pakkub jaotus <em>plokkideks.<\/em> Need vahemikud ei ole enam fikseeritud pikkusega ja omavad rohkem t\u00e4hendust \u2014 reeglina koondavad nad sama t\u00e4hestiku s\u00fcmbolid.<\/p>\n<p><img decoding=\"async\" alt=\"Veel \u00fcks jalgratas: salvestame Unicode&#039;i stringid 30-60% kompaktsemalt kui UTF-8\" src=\"\/wp-content\/uploads\/2020\/10\/61ea5e859d7e6d9c75e977a3579ff28f.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Plokk, mis sisaldab bengali t\u00e4hestiku s\u00fcmboleid. Kahjuks on ajaloolistel p\u00f5hjustel see n\u00e4ide \u00fcsna eba\u00fchtlasest pakkimisest \u2014 96 s\u00fcmbolit on juhuslikult hajutatud 128 koodipunkti vahel plokis.<\/i><\/p>\n<p>Plokkide algused ja nende suurused on alati 16-kordsed \u2014 see on lihtsalt mugavuse t\u00f5ttu. Lisaks, paljud plokid algavad ja l\u00f5ppevad v\u00e4\u00e4rtustes, mis on 128 v\u00f5i isegi 256 kordne \u2013 n\u00e4iteks, p\u00f5hikirillika h\u00f5ivab 256 baiti alates <code><b>0x0400<\/b><\/code> kuni <code><b>0x04FF<\/b><\/code>. See on \u00fcsna mugav: kui salvestame kordumatu prefiksi <code><b>0x04<\/b><\/code>, siis saame igat kirillika s\u00fcmbolit kirjutada \u00fche baitiga. T\u00f5si, me kaotame v\u00f5imaluse tagasi p\u00f6\u00f6rduda ASCII (ja \u00fcksk\u00f5ik milliste teiste s\u00fcmbolite) juurde. Seega teeme j\u00e4rgmist:<\/p>\n<ol>\n<li>Kaks baiti <code><b>10yyyyyy yxxxxxxx<\/b><\/code> ei t\u00e4hista mitte ainult s\u00fcmbolit numbriga <code><b>yyyyyy yxxxxxxx<\/b><\/code>, vaid muudavad <em>kehtivat t\u00e4hestikku<\/em> . Tundub, et <code><b>yyyyyy y0000000<\/b><\/code> (st me salvestame k\u00f5ik bitid, v\u00e4lja arvatud madalamad <strong>7 bitti<\/strong>);<\/li>\n<li>\u00dcks bait <code><b>0xxxxxxx<\/b><\/code> on kehtiva t\u00e4hestiku s\u00fcmbol. Selle tuleb lihtsalt liita selle nihkega, mille me salvestasime sammul 1. Seni, kuni me t\u00e4hestikku ei muuda, on nihke v\u00e4\u00e4rtus null, seega oleme ASCII-ga \u00fchilduvad.<\/li>\n<\/ol>\n<p>\nSarnaselt koodide puhul, mis n\u00f5uavad 3 bait:<\/p>\n<ol>\n<li>Kolm baiti <code><b>110yyyyy yxxxxxxx xxxxxxxx<\/b><\/code> t\u00e4histavad s\u00fcmbolit numbriga <code><b>yyyyyy yxxxxxxx xxxxxxxx<\/b><\/code>, muudab <em>kehtivat t\u00e4hestikku<\/em> . Tundub, et <code><b>yyyyyy y0000000 00000000<\/b><\/code> (salvestame k\u00f5ik, v\u00e4lja arvatud madalamad <strong>15 bitti<\/strong>), ja seab m\u00e4rkeruumi, et oleme n\u00fc\u00fcd <em>pikamas<\/em> re\u017eiimis (t\u00e4hestiku tagasi keeramisel kahekaupa, me t\u00fchistame selle m\u00e4rkeruumi);<\/li>\n<li>Kaks baiti <code><b>0xxxxxxx xxxxxxxx<\/b><\/code> pikamas re\u017eiimis on see kehtiva t\u00e4hestiku s\u00fcmbol. Samuti liidame selle sammul 1 saadud nihkega. K\u00f5ik erinevused on vaid selles, et n\u00fc\u00fcd me loeme kahte baiti (sest me oleme sellesse re\u017eiimi \u00fcle l\u00e4inud).<\/li>\n<\/ol>\n<p>\nTundub hea: n\u00fc\u00fcd, seni kuni peame kodeerima s\u00fcmboleid samas 7-bitises Unicode\u2019i vahemikus, kulutame \u00fche lisabaiti alguses ja vaid \u00fche baidi igas s\u00fcmbolis.<\/p>\n<p><img decoding=\"async\" alt=\"Veel \u00fcks jalgratas: salvestame Unicode&#039;i stringid 30-60% kompaktsemalt kui UTF-8\" src=\"\/wp-content\/uploads\/2020\/10\/084d636a25dccdaa9f5a6eb5233c8e99.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>\u00dche varase versiooni t\u00f6\u00f6. Juba sageli \u00fcletab UTF-8, kuid veel on t\u00e4iustamiseks ruumi.<\/i><\/p>\n<p>Mis on halvenenud? Esiteks, meil on n\u00fc\u00fcd olek, nimelt <em>kehtiva t\u00e4hestiku nihke<\/em> ja m\u00e4rkeruumi <em>pikamas re\u017eiimis<\/em>. See, this additionally restricts us: now the same characters can be encoded differently in different contexts. For example, substring searches will have to take this into account, rather than just comparing bytes. Secondly, once we switched the alphabet, we faced issues with the encoding of ASCII characters (which include not only the Latin alphabet but also basic punctuation, including spaces)\u2014they require a re-switch of the alphabet at 0, meaning an extra byte again (and then another to return to our main one).<\/p>\n<h2>One alphabet is good, two is better<\/h2>\n<p>\nLet's try to slightly change our bit prefixes by squeezing in one more alongside the three described above:<\/p>\n<p><code><b>0xxxxxxx<\/b><\/code> \u2014 1 byte in normal mode, 2 in long mode <br \/>\n<code><b>11xxxxxx<\/b><\/code> \u2014 1 bait <br \/>\n<code><b>100xxxxx xxxxxxxx<\/b><\/code> \u2014 2 baiti <br \/>\n<code><b>101xxxxx xxxxxxxx xxxxxxxx<\/b><\/code> \u2014 3 baiti<\/p>\n<p><img decoding=\"async\" alt=\"Veel \u00fcks jalgratas: salvestame Unicode&#039;i stringid 30-60% kompaktsemalt kui UTF-8\" src=\"\/wp-content\/uploads\/2020\/10\/fa1eca1adb80b15a4cf4f60f57a09c6c.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nNow with two-byte encoding, there's one less available bit\u2014code points fit up to <code><b>0x1FFF<\/b><\/code>, mitte <code><b>0x3FFF<\/b><\/code>. However, it's still significantly more than in two-byte UTF-8 codes; the majority of common languages still fit in, the most noticeable loss is from <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%A5%D0%B8%D1%80%D0%B0%D0%B3%D0%B0%D0%BD%D0%B0\">hiragana<\/a><\/noindex> ja <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%9A%D0%B0%D1%82%D0%B0%D0%BA%D0%B0%D0%BD%D0%B0\">katakana<\/a><\/noindex>, the Japanese are in sadness.<\/p>\n<p>So what is the new code <code><b>11xxxxxx<\/b><\/code>? \u042d\u0442\u043e \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u00ab\u0437\u0430\u0433\u0430\u0448\u043d\u0438\u043a\u00bb \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u043c \u0432 64 \u0441\u0438\u043c\u0432\u043e\u043b\u0430, \u043e\u043d \u0434\u043e\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043d\u0430\u0448 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0430\u043b\u0444\u0430\u0432\u0438\u0442, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u043d\u0430\u0437\u0432\u0430\u043b \u0435\u0433\u043e \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u043c (<em>auxiliary<\/em>) alphabet. When we switch the current alphabet, a piece of the old alphabet becomes auxiliary. For example, switching from ASCII to Cyrillic means we now have 64 characters in the 'warehouse' containing <strong>the Latin alphabet, digits, a space, and a comma<\/strong> (the most common insertions in non-ASCII texts). Switching back to ASCII will make the main part of Cyrillic the auxiliary alphabet.<\/p>\n<p>Thanks to access to two alphabets, we can handle a larger amount of text with minimal switching costs (punctuation will often lead to a return to ASCII, but after that, many non-ASCII characters will be retrieved from the additional alphabet, without re-switching).<\/p>\n<p>Bonus: by designating the additional alphabet with a prefix <code><b>11xxxxxx<\/b><\/code> and setting its initial offset to <code><b>0xC0<\/b><\/code>, we achieve partial compatibility with CP1252. In other words, many (but not all) Western European texts encoded in CP1252 will appear the same in UTF-C.<\/p>\n<p>Here, however, arises the challenge: how to derive an auxiliary alphabet from the main one? You can keep the same offset, but\u2014unfortunately\u2014Unicode structure plays against us here. Very often the main part of the alphabet is not at the beginning of the block (for example, the uppercase 'A' in Russian has code <code>0x04<b>10<\/b><\/code>, kuigi ts\u00fcroliitne blokk algab <code>0x04<b>00<\/b><\/code>). Nii et, v\u00f5ttes \u201evarustusse\u201c esimesed 64 s\u00fcmbolit, v\u00f5ime kaotada ligip\u00e4\u00e4su t\u00e4hestiku l\u00f5pupoolele.<\/p>\n<p>Selle probleemi lahendamiseks k\u00e4isin ma k\u00e4sitsi l\u00e4bi m\u00f5ned plokid, mis vastavad erinevatele keeltele, ja m\u00e4rkisin neile p\u00f5hiallika sees abialfabeedi nihke. Ladina t\u00e4hestikku, erandina, \u00fcmber j\u00e4rjestasin hoopis base64 sarnaselt.<\/p>\n<p><img decoding=\"async\" alt=\"Veel \u00fcks jalgratas: salvestame Unicode&#039;i stringid 30-60% kompaktsemalt kui UTF-8\" src=\"\/wp-content\/uploads\/2020\/10\/d191a3bb17403e99d506dbd008b63159.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<h2>Viimased puudutused<\/h2>\n<p>\nM\u00f5elgem l\u00f5petuseks, kus me saame veel midagi t\u00e4iustada.<\/p>\n<p>Pane t\u00e4hele, et formaat <code><b>101xxxxx xxxxxxxx xxxxxxxx<\/b><\/code> lubab kodeerida numbreid kuni <code><b>0x1FFFFF<\/b><\/code>, kuid Unicode l\u00f5peb varem, number <code><b>0x10FFFF<\/b><\/code>. Teisis\u00f5nu, viimane koodipunkt esindatakse kui <code><b>10110000 11111111 11111111<\/b><\/code>. Nii et, me v\u00f5ime \u00f6elda, et kui esimene bait on kujul <code><b>1011xxxx<\/b><\/code> kui <code><b>xxxx<\/b><\/code> suurem kui 0), siis see t\u00e4histab midagi muud. N\u00e4iteks v\u00f5ib sinna juurde lisada veel 15 s\u00fcmbolit, mis on pidevalt koodimiseks \u00fche baidi jagu, kuid ma otsustasin k\u00e4ituda teisiti.<\/p>\n<p>Vaadakem neid Unicode'i plokke, mis praegu n\u00f5uavad kolme bait: enamasti, nagu mainitud, on need hiina ideogrammid \u2013 aga nendega on raske midagi teha, neid on 21 tuhat. Kuid sinna on juhtunud ka hiragana ja katakana \u2013 neid on juba v\u00e4hem, alla kahesaja. Ja kuna me juba jaapanlastest r\u00e4\u00e4kisime \u2013 seal on ka emotikonid (tegelikult on neid palju jaotatud Unicode'is, kuid p\u00f5hiplokid on vahemikus <code><b>0x1F300<\/b><\/code> \u2013 <code><b>0x1FBFF<\/b><\/code>). Kui m\u00f5elda, et praegu on olemas emotikonid, mis koosnevad mitmest koodipunktist (n\u00e4iteks emotikon \u200d\u200d\u200d<noindex><a rel=\"nofollow\" href=\"https:\/\/emojipedia.org\/family-woman-woman-girl-boy\/\"><img decoding=\"async\" alt=\"Veel \u00fcks jalgratas: salvestame Unicode&#039;i stringid 30-60% kompaktsemalt kui UTF-8\" src=\"\/wp-content\/uploads\/2020\/10\/76cd12423b241cc316af80f03be4348f.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex> koosneb lausa 7 koodist!), siis hakkab t\u00f5eliselt kurb olema raisata iga\u00fchele kolm bait (7\u00d73 = 21 bait \u00fche s\u00fcmboli eest, see on \u00f5udne).<\/p>\n<p>Seet\u00f5ttu valime v\u00e4lja m\u00f5ned valitud vahemikud, mis vastavad emotikonidele, hiraganale ja katakanale, nummerdame need \u00fchte pidevasse loetellu ja kodeerime kahena baidina kolmest:<\/p>\n<p><code><b>1011xxxx xxxxxxxx<\/b><\/code> <\/p>\n<p>Suurep\u00e4rane: eelmainitud emotikon \u200d\u200d\u200d<noindex><a rel=\"nofollow\" href=\"https:\/\/emojipedia.org\/family-woman-woman-girl-boy\/\"><img decoding=\"async\" alt=\"Veel \u00fcks jalgratas: salvestame Unicode&#039;i stringid 30-60% kompaktsemalt kui UTF-8\" src=\"\/wp-content\/uploads\/2020\/10\/b9900c78dda5d8e596e3751021b4d35d.jpeg\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex>, mis koosneb 7 koodipunktist, kasutab UTF-8-s 25 baidi, kuid mahutasime selle <strong>14<\/strong> kahe baitiga igale koodipunktile). Muide, Habra keeldus seda t\u00f6\u00f6tlema (nii vanas kui ka uues toimetajas), nii et tuli see pildina sisestada.<\/p>\n<p>Proovime parandada veel \u00fchte probleemi. Kuidas me m\u00e4letame, et p\u00f5hialfabeet on sisuliselt <strong>\u00fclemised 6 bitti<\/strong>, mida me peame meeles ja kinnitame iga dekooditava s\u00fcmboli koodi. Hiina hierogl\u00fc\u00fcfide puhul, mis asuvad plokis <code><b>0x4E00<\/b><\/code> \u2013 <code><b>0x9FFF<\/b><\/code>, on see kas bit 0 v\u00f5i 1. See pole v\u00e4ga mugav: meil tuleb pidevalt vahetada t\u00e4hestikku nende kahe v\u00e4\u00e4rtuse vahel (st kasutada kolm bitti). Kuid m\u00e4rkame, et pikemas re\u017eiimis saame koodist lahutada s\u00fcmbolite arvu, mida kodeerime l\u00fchikeses re\u017eiimis (aine eelneva kirjeldatud nipi j\u00e4rgi 10240) \u2014 siis nihkub hierogl\u00fc\u00fcfide vahemik <code><b>0x2600<\/b><\/code> \u2013 <code><b>0x77FF<\/b><\/code>, ja sel juhul on kogu selle vahemiku \u00fclemised 6 bitti (21-st) v\u00f5rdsed 0-ga. Seega kasutavad hierogl\u00fc\u00fcfide j\u00e4rjestused iga hierogl\u00fc\u00fcfi jaoks kahte bitti (mis on suurte vahemike jaoks optimaalselt), p\u00f5hjustamata t\u00e4hestiku vahetust. <\/p>\n<h2>Alternatiivsed lahendused: SCSU, BOCU-1<\/h2>\n<p>\nUnicode'i asjatundjad, lugedes ainult artikli nime, kiirustavad t\u00f5en\u00e4oliselt meelde tuletama, et Unicode'i standardite seas on <noindex><a rel=\"nofollow\" href=\"https:\/\/www.unicode.org\/reports\/tr6\/tr6-4.html\">Standard Compression Scheme for Unicode<\/a><\/noindex> (SCSU), mis kirjeldab kodeerimise meetodit, mis on v\u00e4ga sarnane artiklis kirjeldatuga.<\/p>\n<p>Tunnistan ausalt: tema olemasolust sain ma teada alles p\u00e4rast seda, kui olin s\u00fcgavalt oma lahenduse kirjutamisega sisse elanud. Kui oleksin sellest alguses teada, oleksin ilmselt proovinud kirjutada tema rakenduse, mitte v\u00e4lja m\u00f5elda oma l\u00e4henemist.<\/p>\n<p>Huvitav on see, et SCSU kasutab ideid, mis on v\u00e4ga sarnased sellele, milleni ma ise j\u00f5udsin (seal, kus kasutatakse \u201eaknaid\u201c t\u00e4hestiku asemel, on neid rohkem, kui mul on). Samas on sellel formaadil ka miinuseid: see on veidi l\u00e4hemal pakkimisalgoritmidele, mitte kodeerimisele. Eelk\u00f5ige annab standard palju esitlusviise, kuid ei \u00fctle, kuidas neist parimat valida \u2014 selleks peab kodeerija kasutama mingeid heuristikume. Seega on SCSU kodeerija, mis pakub head pakkimist, keerulisem ja mahukam kui minu algoritm.<\/p>\n<p>V\u00f5rdluseks t\u00f5in suhteliselt lihtsa SCSU rakenduse JavaScriptis \u2014 koodi mahult oli see v\u00f5rreldav minu UTF-C-lahendusega, kuid m\u00f5nel juhul n\u00e4itas see tulemusi, mis olid k\u00fcmnete protsentide v\u00f5rra halvemad (m\u00f5nikord v\u00f5ib see ka \u00fcletada, kuid mitte palju). N\u00e4iteks heebrea ja kreeka tekstid kodeeris UTF-C lausa <strong>60% paremini kui SCSU<\/strong> (t\u00f5en\u00e4oliselt t\u00e4nu nende kompaktsetele t\u00e4hestikele).<\/p>\n<p>Lisaks mainin, et lisaks SCSU-le on olemas ka teine kompaktne Unicode'i esitusviis \u2014 <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Binary_Ordered_Compression_for_Unicode\">BOCU-1<\/a><\/noindex>, kuid selle eesm\u00e4rk on saavutada \u00fchilduvus MIME-iga (mida mul ei olnud vaja) ning see kasutab veidi teistsugust kodeerimise l\u00e4henemist. Ma ei ole selle t\u00f5husust hinnanud, kuid mulle tundub, et see ei saa olla efektiivsem kui SCSU.<\/p>\n<h2>V\u00f5imalikud t\u00e4iustused<\/h2>\n<p>\nKasutatud algoritm ei ole disaini poolest universaalne (selle t\u00f5ttu lahknevad mu eesm\u00e4rgid k\u00f5ige rohkem Unicode'i konsortsiumi eesm\u00e4rkidest). Olen juba maininud, et see t\u00f6\u00f6tati v\u00e4lja peamiselt \u00fche \u00fclesande jaoks (mitmekeelse s\u00f5naraamatu salvestamine prefiksipuu kujul), ja m\u00f5ned selle omadused v\u00f5ivad teiste \u00fclesannete jaoks mitte sobida. Kuid fakt, et see ei ole standard, v\u00f5ib olla ka positiivne \u2014 <strong>saate seda h\u00f5lpsasti oma vajadustele kohandada<\/strong>.<\/p>\n<p>N\u00e4iteks on ilmne, et v\u00f5imalik on eemaldada oleku olemasolu, muuta kodeerimine riistadesse mitteoluliseks \u2014 lihtsalt mitte v\u00e4rskendada muutujaid <code><b>kingad<\/b><\/code>, <code><b>auxOffs<\/b><\/code> ja <code><b>is21Bit<\/b><\/code> kodeerijas ja dekodeerijas. Sellisel juhul ei saa efektiivselt pakkida s\u00fcmboolsete j\u00e4rjestusi, kuid on garantii, et sama s\u00fcmbol kodeeritakse alati samade baitidega, s\u00f5ltumata kontekstist.<\/p>\n<p>Lisaks v\u00f5ib kodeerijat kohandada konkreetse keele j\u00e4rgi, muutes vaikeseisundi \u2014 n\u00e4iteks, suunates Venemaa tekstide peale, seadistada alguses kodeerijat ja dekodeerijat <code><b>offs = 0x0400<\/b><\/code> ja <code><b>auxOffs = 0<\/b><\/code>. See on eriti m\u00f5istlik just staatiliste re\u017eiimide korral. \u00dcldiselt sarnaneb see vana 8-bitise kodeerimise kasutamisega, kuid ei v\u00e4lista v\u00f5imalust vajadusel lisada s\u00fcmboleid kogu Unicode'ist.<\/p>\n<p>Veel \u00fcks varem mainitud puudus \u2014 mahukas tekstis, mis on kodeeritud UTF-C-s, ei ole kiiret viisi, kuidas leida s\u00fcmboli piir, mis asub juhusliku baidi l\u00e4hedal. Kui l\u00f5ikate kodeeritud puhverdamist viimased, \u00fctleme, 100 baidi, riskite saada pr\u00fcgi, millega ei saa midagi teha. Suurte logide hoidmiseks ei ole kodeerimine m\u00f5eldud, kuid seda on v\u00f5imalik parandada. Bait <code><b>0xBF<\/b><\/code> ei tohi kunagi esimesena esineda (aga see v\u00f5ib olla teine v\u00f5i kolmas). Seet\u00f5ttu saab kodeerimise k\u00e4igus lisada j\u00e4rjestuse <code><b>0xBF 0xBF 0xBF<\/b><\/code> iga, \u00fctleme, 10 Kb \u2014 siis piisab valitud osa skaneerimisest, et leida piir, kuni sarnane marker on leitud. Viimane <code><b>0xBF<\/b><\/code> garantereeritult on s\u00fcmboli algus. (Dekodeerimisel tuleb see kolmest baitist koosnev j\u00e4rjestus muidugi ignoreerida.)<\/p>\n<h2>Kokkuv\u00f5tteks<\/h2>\n<p>\nKui olete siiani lugenud \u2014 \u00f5nnitleme! Loodan, et olete nagu mina midagi uut \u00f5ppinud (v\u00f5i v\u00e4rskendanud m\u00e4lu) Unicode'i seadistusest.<\/p>\n<p><img decoding=\"async\" alt=\"Veel \u00fcks jalgratas: salvestame Unicode&#039;i stringid 30-60% kompaktsemalt kui UTF-8\" src=\"\/wp-content\/uploads\/2020\/10\/f14b2d815b06a7fda7b77c0a32e7eb75.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Demonstratsioonileht. Heebrea n\u00e4itel on n\u00e4ha eelistusi nii UTF-8 kui ka SCSU ees.<\/i><\/p>\n<p>\u00c4rge k\u00e4sitlege eespool toodud uurimusi standardite rikkumisena. Siiski olen \u00fcldiselt tulemuste \u00fcle rahul ja seet\u00f5ttu olen r\u00f5\u00f5muga <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/deNULL\/utf-c\">valmis neid<\/a><\/noindex>: n\u00e4iteks JS-raamatukogu minimeeritud kujul kaalub vaid 1710 baiti (ja loomulikult ei ole tal s\u00f5ltuvusi). Nagu ma enne mainisin, on selle t\u00f6\u00f6ga v\u00f5imalik tutvuda <noindex><a rel=\"nofollow\" href=\"https:\/\/denull.github.io\/utf-c\/\">demonstreerimislehe<\/a><\/noindex> (seal on ka tekstide komplekt, millega seda saab v\u00f5rrelda UTF-8 ja SCSU-ga).<\/p>\n<p>L\u00f5petuseks tuletan veel kord meelde olukordi, kus UTF-C-d <b>ei tohiks kasutada<\/b>:<\/p>\n<ul>\n<li>Kui teie stringid on piisavalt pikad (100\u2013200 s\u00fcmbolit). Sel juhul tasub m\u00f5elda, kas rakendada kompressioonialgoritme nagu deflate.<\/li>\n<li>Kui teil on vajalik <em>ASCII l\u00e4bitavus<\/em>, see t\u00e4hendab, et teie jaoks on oluline, et kodeeritud j\u00e4rjestustes ei oleks ASCII-koode, mis ei olnud algses stringis. Selle vajaduse saab v\u00e4ltida, kui edastate kodeerimise tulemuse kui abstraktset baitide kogumit, mitte stringidena, kui suhtlete v\u00e4listest API-dest (nt t\u00f6\u00f6tades andmebaasidega). Vastasel juhul riskite etten\u00e4gematute haavatavuste ilmnemisega.<\/li>\n<li>Kui soovite olla suuteline kiiresti leidma s\u00fcmbolite piire suvalise nihkega (n\u00e4iteks kui osa stringist on kahjustatud). Seda saab teha, kuid ainult skaneerides stringi algusest (v\u00f5i rakendades eelmises jaotises kirjeldatud t\u00e4iustust).<\/li>\n<li>Kui teil on vaja kiiresti teha toiminguid stringide sisus (sorteerida neid, otsida alamstringe, konkateerida). Sel juhul tuleb stringid esmalt dekodeerida, seega on UTF-C nendes olukordades aeglasem kui UTF-8 (aga kiirem kompressioonialgoritmidest). Kuna sama string kodeeritakse alati \u00fchtemoodi, ei n\u00f5ua t\u00e4pne dekodeerimise v\u00f5rdlemine selle tegemist baitide kaupa.<\/li>\n<\/ul>\n<p><b>Uuendus:<\/b> kasutaja <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/users\/tyomitch\/\"><b>tyomitch<\/b><\/a><\/noindex> <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/521110\/#comment_22139258\">allpoolt kommentaarides<\/a><\/noindex> Jagasin graafiku, mis r\u00f5hutab UTF-C rakenduse piire. N\u00e4ha on, et UTF-C on efektiivsem kui \u00fcldotstarbelise tihendamise algoritm (LZW variatsioonid), seni kuni tihendatav tekst on l\u00fchem <b>~140 s\u00fcmbolit<\/b> (kuigi pean m\u00e4rkima, et v\u00f5rdlus viidi l\u00e4bi \u00fche teksti p\u00f5hjal; teiste keelte puhul v\u00f5ib tulemus erineda).<br \/>\n<img decoding=\"async\" alt=\"Veel \u00fcks jalgratas: salvestame Unicode&#039;i stringid 30-60% kompaktsemalt kui UTF-8\" src=\"\/wp-content\/uploads\/2020\/10\/0bc9f35ad2757d656801c6466dda09a8.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>Allikas: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/521110\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0438 \u043f\u0435\u0440\u0435\u0434 \u0432\u0430\u043c\u0438 \u0441\u0442\u043e\u0438\u0442 \u0437\u0430\u0434\u0430\u0447\u0430 \u0432\u044b\u0431\u043e\u0440\u0430 \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0438, \u0442\u043e \u043f\u043e\u0447\u0442\u0438 \u0432\u0441\u0435\u0433\u0434\u0430 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u043c \u0440\u0435\u0448\u0435\u043d\u0438\u0435\u043c \u0431\u0443\u0434\u0435\u0442 \u042e\u043d\u0438\u043a\u043e\u0434. \u041a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430, \u043d\u043e \u0447\u0430\u0449\u0435 \u0432\u0441\u0435\u0433\u043e \u0442\u0443\u0442 \u0442\u043e\u0436\u0435 \u0435\u0441\u0442\u044c \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u044b\u0439 \u043e\u0442\u0432\u0435\u0442 \u2014 UTF-8. \u041e\u043d \u0445\u043e\u0440\u043e\u0448 \u0442\u0435\u043c, \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u0441\u0438\u043c\u0432\u043e\u043b\u044b \u042e\u043d\u0438\u043a\u043e\u0434\u0430, \u043d\u0435 \u0442\u0440\u0430\u0442\u044f \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u043c\u043d\u043e\u0433\u043e \u0431\u0430\u0439\u0442 \u0432 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0435 \u0441\u043b\u0443\u0447\u0430\u0435\u0432. \u041f\u0440\u0430\u0432\u0434\u0430, \u0434\u043b\u044f \u044f\u0437\u044b\u043a\u043e\u0432, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0449\u0438\u0445 \u043d\u0435 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":95912,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-95911","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.1.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0415\u0441\u043b\u0438 \u0432\u044b.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/et\/blog\/administrirovanie\/eshhyo-odin-velosiped-hranim-yunikodnye-stroki-na-30-60-kompaktnee-chem-utf-8\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"et_EE\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u0415\u0449\u0451 \u043e\u0434\u0438\u043d \u0432\u0435\u043b\u043e\u0441\u0438\u043f\u0435\u0434: \u0445\u0440\u0430\u043d\u0438\u043c \u044e\u043d\u0438\u043a\u043e\u0434\u043d\u044b\u0435 \u0441\u0442\u0440\u043e\u043a\u0438 \u043d\u0430 30-60% \u043a\u043e\u043c\u043f\u0430\u043a\u0442\u043d\u0435\u0435, \u0447\u0435\u043c UTF-8 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0415\u0441\u043b\u0438 \u0432\u044b.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/et\/blog\/administrirovanie\/eshhyo-odin-velosiped-hranim-yunikodnye-stroki-na-30-60-kompaktnee-chem-utf-8\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-10-04T23:42:09+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-10-04T23:42:09+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Veel \u00fcks uus s\u00f5iduk: hoiame Unicode'i stringe 30-60% kompaktsemalt kui UTF-8 | ProHoster","description":"Kui sa.","canonical_url":"https:\/\/prohoster.info\/et\/blog\/administrirovanie\/eshhyo-odin-velosiped-hranim-yunikodnye-stroki-na-30-60-kompaktnee-chem-utf-8","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"et_EE","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u0415\u0449\u0451 \u043e\u0434\u0438\u043d \u0432\u0435\u043b\u043e\u0441\u0438\u043f\u0435\u0434: \u0445\u0440\u0430\u043d\u0438\u043c \u044e\u043d\u0438\u043a\u043e\u0434\u043d\u044b\u0435 \u0441\u0442\u0440\u043e\u043a\u0438 \u043d\u0430 30-60% \u043a\u043e\u043c\u043f\u0430\u043a\u0442\u043d\u0435\u0435, \u0447\u0435\u043c UTF-8 | ProHoster","og:description":"\u0415\u0441\u043b\u0438 \u0432\u044b.","og:url":"https:\/\/prohoster.info\/et\/blog\/administrirovanie\/eshhyo-odin-velosiped-hranim-yunikodnye-stroki-na-30-60-kompaktnee-chem-utf-8","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-10-04T23:42:09+00:00","article:modified_time":"2020-10-04T23:42:09+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"95911","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 10:55:40","updated":"2022-09-29 03:35:04","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/posts\/95911","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/comments?post=95911"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/posts\/95911\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/media\/95912"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/media?parent=95911"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/categories?post=95911"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/tags?post=95911"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}