Дигар велосипед: мо сатрҳои Юникодро нисбат ба UTF-30 60-8% зичтар нигоҳ медорем

Дигар велосипед: мо сатрҳои Юникодро нисбат ба UTF-30 60-8% зичтар нигоҳ медорем

Агар шумо таҳиягар бошед ва шумо бо вазифаи интихоби рамзгузорӣ дучор шуда бошед, Юникод қариб ҳамеша ҳалли дуруст хоҳад буд. Усули мушаххаси муаррифӣ аз контекст вобаста аст, аммо аксар вақт дар ин ҷо ҷавоби универсалӣ вуҷуд дорад - UTF-8. Чизи хуби он дар он аст, ки он ба шумо имкон медиҳад, ки ҳама аломатҳои Юникодро бидуни харҷ истифода баред хеле зиёд аст дар аксар мавридҳо байтҳои зиёд. Дуруст аст, ки барои забонҳое, ки на танҳо алифбои лотинӣ истифода мебаранд, ҳадди аққал "на он қадар зиёд" аст ду байт барои як аломат. Оё мо метавонем бе бозгашт ба рамзгузории пеш аз таърихӣ, ки моро танҳо бо 256 аломати дастрас маҳдуд мекунанд, беҳтар кор кунем?

Дар зер ман пешниҳод мекунам, ки бо кӯшиши ман барои посух додан ба ин савол шинос шавам ва як алгоритми нисбатан соддаро амалӣ созам, ки ба шумо имкон медиҳад, ки хатҳоро дар аксари забонҳои ҷаҳон бидуни илова кардани изофӣ дар UTF-8 нигоҳ доред.

Радди масъулият. Ман фавран якчанд қайдҳои муҳимро хоҳам гузошт: ҳалли тавсифшуда ҳамчун ивазкунандаи универсалии UTF-8 пешниҳод карда намешавад, он танҳо дар рӯйхати танги парвандаҳо мувофиқ аст (бештар дар бораи онҳо дар поён) ва ба ҳеҷ ваҷҳ набояд барои ҳамкорӣ бо API-ҳои тарафи сеюм истифода шавад (ки ҳатто дар бораи он намедонанд). Аксар вақт, алгоритмҳои фишурдани таъиноти умумӣ (масалан, deflate) барои нигоҳдории паймоне, ки ҳаҷми калони маълумоти матнӣ доранд, мувофиқанд. Илова бар ин, аллакай дар раванди эҷоди ҳалли худ, ман дар худи Юникод як стандарти мавҷударо пайдо кардам, ки ҳамон мушкилотро ҳал мекунад - он то андозае мураккабтар аст (ва аксаран бадтар), аммо ба ҳар ҳол он стандарти қабулшуда аст ва на танҳо гузошта шудааст. якҷоя дар зону. Ман ба шумо дар бораи ӯ ҳам нақл мекунам.

Дар бораи Юникод ва UTF-8

Барои оғоз, чанд сухан дар бораи он чӣ аст Unicode и UTF-8.

Тавре ки шумо медонед, рамзгузории 8-битӣ маъмул буд. Бо онҳо ҳама чиз оддӣ буд: 256 аломатро бо рақамҳои аз 0 то 255 рақамгузорӣ кардан мумкин аст ва рақамҳои аз 0 то 255 метавонанд ҳамчун як байт нишон дода шаванд. Агар мо ба ибтидо баргардем, рамзгузории ASCII комилан бо 7 бит маҳдуд аст, бинобар ин муҳимтарин бит дар муаррифии байт сифр аст ва аксари рамзгузории 8-битӣ бо он мувофиқанд (онҳо танҳо дар "болоӣ" фарқ мекунанд. қисме, ки дар он бит муҳимтарин як аст).

Юникод аз ин рамзгузорӣ чӣ фарқ дорад ва чаро ин қадар намояндаҳои мушаххас бо он алоқаманданд - UTF-8, UTF-16 (BE ва LE), UTF-32? Биёед онро бо тартиб ба тартиб андозем.

Стандарти асосии Юникод танҳо мувофиқати байни аломатҳо (ва дар баъзе ҳолатҳо ҷузъҳои алоҳидаи аломатҳо) ва рақамҳои онҳоро тавсиф мекунад. Ва дар ин стандарт шумораи зиёди рақамҳои имконпазир мавҷуданд - аз 0x00 ба 0x10FFFF (1 дона). Агар мо мехостем як ададро дар чунин диапазон ба тағирёбанда гузорем, на 114 ва на 112 байт барои мо кифоя намекунад. Ва азбаски протсессорҳои мо барои кор бо рақамҳои се байтӣ он қадар тарҳрезӣ нашудаанд, мо маҷбур мешавем, ки барои ҳар як аломат то 1 байт истифода барем! Ин UTF-2 аст, аммо маҳз аз ҳамин "исрофкорӣ" ин формат маъмул нест.

Хушбахтона, тартиби аломатҳо дар Юникод тасодуфӣ нест. Тамоми маҷмӯи онҳо ба 17 тақсим карда шудааст "самолётхо", ки ҳар яки онҳо 65536 (0x10000) "нуқтаҳои код" Мафҳуми "нуқтаи рамзӣ" дар ин ҷо оддӣ аст рақами аломат, ба он аз ҷониби Юникод таъин шудааст. Аммо, тавре ки дар боло зикр гардид, дар Юникод на танҳо аломатҳои инфиродӣ рақамгузорӣ карда мешаванд, балки ҷузъҳо ва аломатҳои хидматрасонии онҳо (ва баъзан ҳеҷ чиз ба рақам мувофиқат намекунад - шояд дар айни замон, аммо барои мо ин он қадар муҳим нест), бинобар ин дурусттар аст, ки ҳамеша дар бораи шумораи худи рақамҳо сухан гӯед, на аломатҳо. Бо вуҷуди ин, дар зер, барои кӯтоҳ кардан, ман аксар вақт калимаи "рамзро" истифода мебарам, ки истилоҳи "нуқтаи код" -ро дар назар дорад.

Дигар велосипед: мо сатрҳои Юникодро нисбат ба UTF-30 60-8% зичтар нигоҳ медорем
Ҳавопаймоҳои Юникод. Чунон ки мебинед, кисми зиёди он (самолётхои аз 4 то 13) хануз истифоданашудаанд.

Муҳимтар аз ҳама он аст, ки тамоми "селлюлоза" дар ҳавопаймои сифр ҷойгир аст, ки онро "Ҳавопаймои бисёрзабона". Агар сатр дорои матн бо яке аз забонҳои муосир (аз ҷумла чинӣ) бошад, шумо аз ин сатҳ берун намеравед. Аммо шумо наметавонед боқимондаи Юникодро буред - масалан, эмодзиҳо асосан дар охири забон ҷойгир шудаанд. ҳавопаймои навбатӣ"Ҳавопаймои иловагӣ"(аз он дароз мешавад 0x10000 ба 0x1FFFF). Ҳамин тавр, UTF-16 ин корро мекунад: ҳамаи аломатҳои ба дохили он дохилшаванда Ҳавопаймои бисёрзабона, бо рақами мувофиқи ду байт рамзгузорӣ карда мешаванд. Аммо, баъзе рақамҳо дар ин диапазон умуман аломатҳои мушаххасро нишон намедиҳанд, аммо нишон медиҳанд, ки пас аз ин ҷуфти байт мо бояд дигареро баррасӣ кунем - бо якҷоя кардани арзишҳои ин чаҳор байт, мо рақамеро ба даст меорем, ки тамоми диапазони дурусти Юникод. Ин идеяро "ҷуфтҳои суррогатӣ" меноманд - шумо шояд дар бораи онҳо шунидаед.

Ҳамин тавр, UTF-16 барои як "нуқтаи код" ду ё (дар ҳолатҳои хеле кам) чаҳор байт талаб мекунад. Ин беҳтар аз истифодаи чор байт ҳама вақт аст, аммо лотинӣ (ва дигар аломатҳои ASCII) ҳангоми рамзгузорӣ бо ин роҳ нисфи ҷойро дар сифрҳо барбод медиҳад. UTF-8 барои ислоҳи ин пешбинӣ шудааст: ASCII дар он мисли пештара танҳо як байтро ишғол мекунад; рамзҳо аз 0x80 ба 0x7FF - ду байт; аз 0x800 ба 0xFFFF - се, ва аз 0x10000 ба 0x10FFFF - чор. Аз як тараф, алифбои лотинӣ хуб шуд: мутобиқат бо ASCII баргашт ва тақсимот аз 1 то 4 байт баробартар “паҳн шуд”. Аммо алифбои ғайр аз лотинӣ, мутаассифона, дар муқоиса бо UTF-16 ба ҳеҷ ваҷҳ фоидае надорад ва ҳоло бисёриҳо ба ҷои ду се байт талаб мекунанд - диапазони фарогирии сабти дубайтӣ 32 маротиба танг шудааст, бо 0xFFFF ба 0x7FF, ва на чинй ва на масалан, грузин ба он дохил карда нашудааст. Кириллик ва панҷ алифбои дигар - хуррей - бахти, 2 байт ба як аломат.

Чаро ин рӯй медиҳад? Биёед бубинем, ки чӣ тавр UTF-8 рамзҳои аломатҳоро ифода мекунад:
Дигар велосипед: мо сатрҳои Юникодро нисбат ба UTF-30 60-8% зичтар нигоҳ медорем
Дар ин ҷо мустақиман барои муаррифии рақамҳо битҳои бо аломат ишорашуда истифода мешаванд x. Мумкин аст, ки дар як сабти дубайтӣ танҳо 11 чунин бит (аз 16) мавҷуд аст. Битҳои пешбари ин ҷо танҳо вазифаи ёрирасон доранд. Дар сурати сабти чаҳор байт, 21 аз 32 бит барои рақами нуқтаи код ҷудо карда мешавад - чунин ба назар мерасад, ки се байт (ки ҳамагӣ 24 бит медиҳад) кофӣ хоҳад буд, аммо нишонгузорҳои хидматрасонӣ аз ҳад зиёд мехӯранд.

Оё ин бад аст? На дарвоқеъ. Аз як тараф, агар мо дар бораи фазо бисёр ғамхорӣ кунем, мо алгоритмҳои фишурдасозиро дорем, ки метавонанд ҳама энтропия ва зиёдатӣ ба осонӣ бартараф карда шаванд. Аз тарафи дигар, ҳадафи Юникод таъмин кардани рамзгузории универсалтарин буд. Масалан, мо метавонем як сатри дар UTF-8 рамзгузоришударо ба рамзе супорем, ки қаблан танҳо бо ASCII кор мекард ва натарсед, ки он аломатеро аз диапазони ASCII мебинад, ки воқеан вуҷуд надорад (охир дар UTF-8 ҳама байтҳое, ки аз бит аз сифр сар мешаванд - ин маҳз ҳамон чизест, ки ASCII аст). Ва агар мо ногаҳон бихоҳем, ки думи хурдро аз сатри калон бидуни рамзкушоӣ аз аввал бурида (ё як қисми маълумотро пас аз қисмати вайроншуда барқарор кунем), барои мо осон аст, ки ҷубронеро, ки аломат сар мешавад (кифоя аст) байтҳоеро, ки префикси каме доранд, гузаред 10).

Пас чаро чизи навро ихтироъ мекунанд?

Дар айни замон, баъзан ҳолатҳое мешаванд, ки алгоритмҳои фишурдакунӣ ба монанди deflate суст татбиқ мешаванд, аммо шумо мехоҳед нигоҳдории паймонҳои сатрҳоро ба даст оред. Шахсан ман ҳангоми андеша дар бораи сохтмон ба ин мушкилот дучор шудам дарахти префикси фишурдашуда барои луғати калон, аз ҷумла калимаҳо дар забонҳои худсарона. Аз як тараф, ҳар як калима хеле кӯтоҳ аст, бинобар ин фишурдани он бесамар хоҳад буд. Аз тарафи дигар, татбиқи дарахте, ки ман баррасӣ кардам, тавре тарҳрезӣ шуда буд, ки ҳар як байт аз сатри захирашуда қуллаи дарахти алоҳида тавлид кунад, аз ин рӯ кам кардани шумораи онҳо хеле муфид буд. Дар китобхонаи ман Az.js (Чунон ки дар пиморфия 2, ки ба он асос ёфтааст) мушкилоти шабеҳро метавон ба осонӣ ҳал кард - сатрҳо ба бастабандӣ DAWG-луғат, ки дар он ҷо нигоҳ дошта мешавад кӯҳнаи хуби CP1251. Аммо, чунон ки фаҳмидан осон аст, ин танҳо барои алифбои маҳдуд хуб кор мекунад - хати чиниро ба чунин луғат илова кардан мумкин нест.

Алоҳида, ман мехоҳам боз як нозукии нохушеро қайд намоям, ки ҳангоми истифодаи UTF-8 дар чунин сохтори додаҳо ба вуҷуд меояд. Тасвири боло нишон медиҳад, ки ҳангоми навиштани аломат ҳамчун ду байт, битҳои марбут ба рақами он дар як саф намеоянд, балки бо як ҷуфт бит ҷудо мешаванд. 10 дар байн: 110xxxxx 10xxxxxx. Аз ин сабаб, вақте ки 6 битҳои поёнии байти дуюм дар рамзи аломат пур мешавад (яъне гузариш ба амал меояд) 1011111110000000), пас байти аввал низ дигар мешавад. Маълум мешавад, ки ҳарфи «п» бо байт ишора шудааст 0xD0 0xBF, ва "r"-и навбатӣ аллакай аст 0xD1 0x80. Дар дарахти префикс ин ба ду тақсим шудани гиреҳи волидайн оварда мерасонад - яке барои префикс 0xD0, ва дигаре барои 0xD1 (ҳарчанд тамоми алифбои кириллӣ танҳо бо байти дуюм рамзгузорӣ шуда метавонист).

Ман чӣ гирифтам

Бо ин мушкилот рӯ ба рӯ шуда, ман қарор додам, ки бозӣ бо битҳо машқ кунам ва ҳамзамон бо сохтори Юникод дар маҷмӯъ каме беҳтар шинос шавам. Дар натиҷа формати рамзгузории UTF-C ("C" барои зич), ки барои як нуқтаи рамз на бештар аз 3 байт сарф мекунад ва аксар вақт ба шумо имкон медиҳад, ки танҳо сарф кунед як байти иловагӣ барои тамоми хати рамзгузоришуда. Ин ба он оварда мерасонад, ки дар бисёре аз алифбоҳои ғайри ASCII чунин рамзгузорӣ рӯй медиҳад 30-60% зичтар аз UTF-8.

Ман мисолҳои татбиқи алгоритмҳои рамзгузорӣ ва рамзкушоиро дар шакл пешниҳод кардам Китобхонаҳои JavaScript ва Go, шумо метавонед онҳоро дар коди худ озодона истифода баред. Аммо ман то ҳол таъкид мекунам, ки ин формат ба маънои "велосипед" боқӣ мемонад ва ман истифодаи онро тавсия намедиҳам. бе он ки ба шумо барои чӣ лозим аст. Ин ҳоло ҳам бештар як таҷриба аст, на як "беҳбудии ҷидии UTF-8". Бо вуҷуди ин, код дар он ҷо дақиқ, мухтасар, бо шумораи зиёди шарҳҳо ва фарогирии санҷиш навишта шудааст.

Дигар велосипед: мо сатрҳои Юникодро нисбат ба UTF-30 60-8% зичтар нигоҳ медорем
Натиҷаҳои санҷиш ва муқоиса бо UTF-8

Ман ҳам кардам саҳифаи намоишӣ, ки дар он шумо метавонед иҷрои алгоритмро арзёбӣ кунед ва он гоҳ ман ба шумо дар бораи принсипҳо ва раванди таҳияи он бештар нақл мекунам.

Бартараф кардани битҳои зиёдатӣ

Ман, албатта, UTF-8-ро асос гирифтам. Аввалин ва равшантарин чизе, ки дар он тағир додан мумкин аст, кам кардани шумораи битҳои хидматрасонӣ дар ҳар як байт мебошад. Масалан, байти аввал дар UTF-8 ҳамеша бо яке оғоз мешавад 0, ё бо 11 - префикс 10 Танҳо байтҳои зерин онро доранд. Биёед префиксро иваз кунем 11 ба 1, ва барои байтҳои оянда мо префиксҳоро комилан хориҷ мекунем. Чӣ мешавад?

0xxxxxxx — 1 байт
10xxxxxx xxxxxxxx - 2 байт
110xxxxx xxxxxxxx xxxxxxxx - 3 байт

Мунтазир бошед, сабти чор байтӣ куҷост? Аммо он дигар лозим нест - ҳангоми навиштан дар се байт, мо ҳоло 21 бит дорем ва ин барои ҳама рақамҳо кифоя аст. 0x10FFFF.

Мо дар ин ҷо чӣ қурбонӣ кардем? Муҳимтар аз ҳама, муайян кардани сарҳадҳои аломатҳо аз макони худсарона дар буфер аст. Мо наметавонем ба як байти худсарона ишора кунем ва аз он ибтидои аломати ояндаро пайдо кунем. Ин маҳдудияти формати мост, аммо дар амал ин хеле кам зарур аст. Мо одатан қодирем, ки аз ибтидо аз буфер гузарем (хусусан вақте ки сухан дар бораи хатҳои кӯтоҳ меравад).

Вазъияти фарогирии забонҳо бо 2 байт низ беҳтар шудааст: ҳоло формати дубайтӣ диапазони 14 бит медиҳад ва инҳо рамзҳо мебошанд 0x3FFF. Чиниҳо бадбахтанд (ҳарфҳои онҳо асосан аз 0x4E00 ба 0x9FFF), аммо гурҷиҳо ва бисёр халқҳои дигар шавқовартаранд - забонҳои онҳо низ ба 2 байт барои ҳар як аломат мувофиқат мекунанд.

Ҳолати рамзгузорро ворид кунед

Акнун биёед дар бораи хосиятҳои худи хатҳо фикр кунем. Луғат аксар вақт калимаҳоеро дар бар мегирад, ки бо ҳарфҳои як алифбо навишта шудаанд ва ин ба бисёр матнҳои дигар низ дахл дорад. Хуб мешуд, ки ин алифбо як бор нишон дода, баъд танҳо шумораи ҳарфи дохили он нишон дода шавад. Биёед бубинем, ки оё ҷойгиркунии аломатҳо дар ҷадвали Юникод ба мо кӯмак мекунад?

Тавре ки дар боло зикр гардид, Юникод ба тақсим мешавад ҳавопаймо Ҳар як 65536 код. Аммо ин тақсимоти хеле муфид нест (чунон ки аллакай гуфта шудааст, мо аксар вақт дар ҳавопаймои сифр ҳастем). Ҷолибтар аз он тақсимот аст блокҳо Ин диапазонҳо дигар дарозии собит надоранд ва пурмазмунтаранд - чун қоида, ҳар як аломатҳои як алифборо муттаҳид мекунад.

Дигар велосипед: мо сатрҳои Юникодро нисбат ба UTF-30 60-8% зичтар нигоҳ медорем
Блоки дорои аломатҳои алифбои бенгалӣ. Мутаассифона, бо сабабҳои таърихӣ, ин намунаи бастабандии на он қадар зич аст - 96 аломат дар 128 нуқтаи рамзи блок бетартибона пароканда шудаанд.

Оғози блокҳо ва андозаи онҳо ҳамеша чандкаратаи 16 мебошанд - ин танҳо барои роҳат анҷом дода мешавад. Илова бар ин, бисёре аз блокҳо бо арзишҳое оғоз ва анҷом меёбанд, ки ба 128 ё ҳатто 256 баробар мебошанд - масалан, алифбои асосии кириллӣ аз 256 байт мегирад. 0x0400 ба 0x04FF. Ин хеле қулай аст: агар мо префиксро як маротиба захира кунем 0x04, пас дар як байт ҳар ҳарфи кириллӣ навишта мешавад. Дуруст аст, ки бо ин роҳ мо имкони баргаштан ба ASCII (ва умуман ба ҳар гуна аломатҳои дигар) аз даст медиҳем. Аз ин рӯ, мо ин корро мекунем:

  1. Ду байт 10yyyyyy yxxxxxxx на танхо аломатро бо адад ифода мекунанд yyyyyy yxxxxxxx, балки низ тагьир меёбад алифбои ҷорӣ ба yyyyyy y0000000 (яъне мо ҳама битҳоро дар хотир дорем, ба истиснои қисмҳои камтарин 7 битавонад);
  2. Як байт 0xxxxxxx ин характери алифбои хозира аст. Он танҳо бояд ба ҷубронпулие, ки мо дар қадами 1 дар ёд доштем, илова кардан лозим аст. Дар ҳоле, ки мо алифборо тағир надодаем, офсет сифр аст, бинобар ин мо мувофиқатро бо ASCII нигоҳ доштем.

Ҳамин тавр барои рамзҳое, ки 3 байтро талаб мекунанд:

  1. Се байт 110yyyyy yxxxxxxx xxxxxxxx аломатеро бо рақам нишон диҳед yyyyyy yxxxxxxx xxxxxxxx, иваз кардан алифбои ҷорӣ ба yyyyyy y0000000 00000000 (ба гайр аз хурдсолон хама чизро ба хотир овард 15 битавонад) ва қуттиеро, ки мо ҳоло дар он ҳастем, қайд кунед дароз режим (ҳангоми иваз кардани алифбо ба алифбои дубайтӣ, мо ин парчамро аз нав танзим мекунем);
  2. Ду байт 0xxxxxxx xxxxxxxx дар реҷаи дароз он хусусияти алифбои ҷорӣ аст. Ҳамин тавр, мо онро бо офсет аз қадами 1 илова мекунем. Ягона фарқият дар он аст, ки ҳоло мо ду байт мехонем (зеро мо ба ин режим гузаштем).

Хуб садо медиҳад: ҳоло дар ҳоле ки мо бояд аломатҳоро аз ҳамон диапазони 7-битаи Юникод рамзгузорӣ кунем, мо дар аввал 1 байти иловагӣ ва ҳамагӣ як байт барои як аломат сарф мекунем.

Дигар велосипед: мо сатрҳои Юникодро нисбат ба UTF-30 60-8% зичтар нигоҳ медорем
Кор аз яке аз версияҳои қаблӣ. Он аллакай аксар вақт UTF-8-ро мағлуб мекунад, аммо барои такмил вуҷуд дорад.

Чӣ бадтар аст? Аввалан, мо шарт дорем, яъне офсети алифбои ҷорӣ ва қуттии қайд режими дароз. Ин моро боз ҳам маҳдуд мекунад: акнун як аломатҳоро дар контекстҳои гуногун ба таври гуногун рамзгузорӣ кардан мумкин аст. Ҷустуҷӯи зерсатрҳо, масалан, бояд бо назардошти ин анҷом дода шавад, на танҳо бо муқоисаи байт. Сониян, ҳамин ки мо алифборо иваз кардем, бо рамзгузории аломатҳои ASCII вазъ бад шуд (ва ин на танҳо алифбои лотинӣ, балки аломатҳои пунктуатсияи асосӣ, аз ҷумла фосилаҳо низ мебошад) - онҳо талаб мекунанд, ки алифборо дубора ба 0 иваз кунанд, яъне боз як байти иловагӣ (ва баъд як байти дигар барои баргаштан ба нуқтаи асосии мо).

Як алифбо хуб аст, ду алифбо беҳтар аст

Биёед кӯшиш кунем, ки пешояндҳои битҳои худро каме тағир диҳем ва яктои дигарро ба сеи дар боло тавсифшуда фишурда кунем:

0xxxxxxx — 1 байт дар реҷаи муқаррарӣ, 2 дар ҳолати дароз
11xxxxxx — 1 байт
100xxxxx xxxxxxxx - 2 байт
101xxxxx xxxxxxxx xxxxxxxx - 3 байт

Дигар велосипед: мо сатрҳои Юникодро нисбат ба UTF-30 60-8% зичтар нигоҳ медорем

Ҳоло дар сабти ду-байтӣ як бит камтар дастрас аст - код то ба он ишора мекунад 0x1FFFва не 0x3FFF. Бо вуҷуди ин, он ҳанӯз ҳам нисбат ба рамзҳои дубайтии UTF-8 ба таври назаррас калонтар аст, забонҳои маъмултарин ҳоло ҳам мувофиқанд, талафоти назаррас коҳиш ёфтааст хирагана и катакана, японхо гамгинанд.

Ин рамзи нав чист? 11xxxxxx? Ин як "саш"-и хурди дорои 64 аломат аст, ки алифбои асосии моро пурра мекунад, бинобар ин ман онро ёрирасон номидам (ёрирасон) алифбо. Вақте ки мо алифбои ҷорӣро иваз мекунем, як пораи алифбои кӯҳна ёрирасон мешавад. Масалан, мо аз ASCII ба кириллӣ гузаштем - stash ҳоло 64 аломатро дар бар мегирад, ки Алифбои лотинӣ, рақамҳо, фосила ва вергул (аз ҳама бештар воридкунӣ дар матнҳои ғайри ASCII). Бозгашт ба ASCII - ва қисми асосии алифбои кириллӣ ба алифбои ёрирасон табдил меёбад.

Бо шарофати дастрасӣ ба ду алифбо, мо метавонем миқдори зиёди матнҳоро бо хароҷоти ҳадди ақал барои иваз кардани алифбо идора кунем (пунктуатсия аксар вақт боиси бозгашт ба ASCII мегардад, аммо баъд аз он мо аз алифбои иловагӣ аломатҳои зиёди ғайри ASCII мегирем. дубора иваз кардан).

Бонус: префикси зералифбо 11xxxxxx ва интихоби ҷуброни ибтидоии он 0xC0, мо мутобиқати қисман бо CP1252 мегирем. Ба ибораи дигар, бисёр (вале на ҳама) матнҳои Аврупои Ғарбӣ, ки дар CP1252 рамзгузорӣ шудаанд, дар UTF-C якхела хоҳанд буд.

Аммо дар ин чо душворй ба миён меояд: чй тавр аз алифбои асосй алифбои ёрирасонро гирифтан мумкин аст? Шумо метавонед ҳамон офсетро тарк кунед, аммо, мутаассифона, дар ин ҷо сохтори Юникод аллакай бар зидди мо бозӣ мекунад. Аксар вақт қисми асосии алифбо дар ибтидои блок нест (масалан, пойтахти Русия "А" рамз дорад. 0x0410, гарчанде ки блоки сириллик бо оғоз мешавад 0x0400). Ҳамин тариқ, бо гирифтани 64 аломати аввал ба хазина, мо метавонем дастрасӣ ба қисми думи алифборо аз даст диҳем.

Барои ислоҳи ин мушкилот, ман дастӣ аз якчанд блокҳои мувофиқи забонҳои гуногун гузаштам ва ҷуброни алифбои ёрирасонро дар доираи алифбои асосӣ барои онҳо муайян кардам. Алифбои лотинӣ, ҳамчун истисно, умуман ба монанди base64 аз нав тартиб дода шуд.

Дигар велосипед: мо сатрҳои Юникодро нисбат ба UTF-30 60-8% зичтар нигоҳ медорем

Лахзаҳои ниҳоӣ

Биёед дар ниҳоят дар бораи он фикр кунем, ки дар куҷо мо чизеро беҳтар карда метавонем.

Дар хотир доред, ки формат 101xxxxx xxxxxxxx xxxxxxxx ба шумо имкон медиҳад, ки рақамҳоро то ба код созед 0x1FFFFF, ва Юникод пештар ба охир мерасад, дар 0x10FFFF. Ба ибораи дигар, нуқтаи охирини код ҳамчун нишон дода мешавад 10110000 11111111 11111111. Бинобар ин метавон гуфт, ки агар байти аввал аз шакл бошад 1011xxxx (Дар куҷо xxxx бузургтар аз 0), пас ин маънои дигарро дорад. Масалан, шумо метавонед 15 аломати дигарро дар он ҷо илова кунед, ки ҳамеша барои рамзгузорӣ дар як байт дастрасанд, аммо ман қарор додам, ки онро ба таври дигар иҷро кунам.

Биёед ба он блокҳои Юникод назар андозем, ки ҳоло се байтро талаб мекунанд. Асосан, тавре ки аллакай зикр гардид, инҳо аломатҳои чинӣ мебошанд - аммо бо онҳо кор кардан душвор аст, 21 ҳазор нафари онҳо ҳастанд. Аммо хирагана ва катакана низ он ҷо парвоз карданд - ва онҳо ҳоло он қадар зиёд нестанд, камтар аз дусад нафар. Ва азбаски мо японҳоро ба ёд овардем, эмодзиҳо низ ҳастанд (воқеан, онҳо дар Юникод дар бисёр ҷойҳо парокандаанд, аммо блокҳои асосӣ дар диапазон ҳастанд. 0x1F300 - 0x1FBFF). Агар шумо дар бораи он фикр кунед, ки ҳоло эмодзиҳо мавҷуданд, ки якбора аз якчанд нуқтаи рамз ҷамъ карда мешаванд (масалан, эмодзиҳо ‍‍‍Дигар велосипед: мо сатрҳои Юникодро нисбат ба UTF-30 60-8% зичтар нигоҳ медорем аз 7 код иборат аст!), пас барои ҳар кадом се байт сарф кардан (7×3 = 21 байт ба хотири як нишона, даҳшат) айб аст.

Аз ин рӯ, мо якчанд диапазони интихобшударо, ки ба эмодзи, хирагана ва катакана мувофиқанд, интихоб мекунем, онҳоро ба як рӯйхати пайваста рақамгузорӣ мекунем ва онҳоро ба ҷои се байт ҳамчун ду байт рамзгузорӣ мекунем:

1011xxxx xxxxxxxx

Бузург: эмодзии дар боло зикршудаДигар велосипед: мо сатрҳои Юникодро нисбат ба UTF-30 60-8% зичтар нигоҳ медорем, ки аз 7 нуқтаи рамзӣ иборат аст, дар UTF-8 25 байт мегирад ва мо ба он мувофиқат мекунем 14 (ду байт барои ҳар як нуқтаи код). Воқеан, Ҳабр аз ҳазми он (ҳам дар муҳаррири кӯҳна ва ҳам дар муҳаррири нав) худдорӣ кард, бинобар ин ман маҷбур шудам, ки онро бо расм ворид кунам.

Биёед боз як мушкилиро ҳал кунем. Тавре ки мо дар хотир дорем, алифбои асосӣ аслан аст баланд 6 бит, ки мо онро дар хотир нигоҳ медорем ва ба рамзи ҳар як рамзи рамзкушодашуда мечаспам. Дар мавриди аломатҳои чинӣ, ки дар блок ҳастанд 0x4E00 - 0x9FFF, ин бит 0 ё 1 аст. Ин чандон қулай нест: ба мо лозим меояд, ки пайваста алифборо байни ин ду арзиш иваз кунем (яъне се байт сарф кунем). Аммо дар хотир доред, ки дар реҷаи дароз аз худи код мо метавонем шумораи аломатҳоеро, ки мо бо истифода аз реҷаи кӯтоҳ рамзгузорӣ мекунем, хориҷ кунем (пас аз ҳама ҳиллаҳои дар боло тавсифшуда, ин 10240 аст) - он гоҳ диапазони иероглифҳо ба тағйир хоҳанд ёфт. 0x2600 - 0x77FF, ва дар ин ҳолат, дар тамоми ин диапазон, муҳимтарин 6 бит (аз 21) ба 0 баробар хоҳад буд. Ҳамин тариқ, пайдарпайии иероглифҳо барои ҳар як иероглиф ду байт истифода хоҳанд кард (ки барои чунин диапазони калон мувофиқ аст), бидуни боиси ивазшавии алифбо мегардад.

Роҳҳои алтернативӣ: SCSU, BOCU-1

Коршиносони Юникод бо хондани сарлавҳаи мақола, эҳтимолан ба шумо шитоб мекунанд, ки ба шумо хотиррасон кунанд, ки бевосита дар байни стандартҳои Юникод вуҷуд дорад. Нақшаи стандартии фишурдани Юникод (SCSU), ки усули рамзгузории хеле шабеҳро ба усули дар мақола тавсифшуда тавсиф мекунад.

Ман ростқавлона иқрор мешавам: ман дар бораи мавҷудияти он танҳо пас аз он ки дар навиштани қарори худ амиқ ғарқ шудам, фаҳмидам. Агар ман дар бораи он аз аввал медонистам, ман эҳтимол кӯшиш мекардам, ки ба ҷои он ки равиши шахсии худро таҳия кунам, як амалисозӣ нависам.

Ҷолиб он аст, ки SCSU ғояҳоеро истифода мебарад, ки ман худам таҳия кардам (ба ҷои мафҳуми “алифбо” онҳо “равзанаҳо”-ро истифода мебаранд ва шумораи онҳо назар ба ман дастрас аст). Дар баробари ин, ин формат камбудиҳо низ дорад: он нисбат ба алгоритмҳои рамзгузорӣ ба алгоритмҳои фишурда каме наздиктар аст. Аз ҷумла, стандарт усулҳои зиёди муаррифиро медиҳад, аммо намегӯяд, ки чӣ гуна интихоб кардани оптималӣ - барои ин, рамзгузор бояд як навъ эвристикаро истифода барад. Ҳамин тариқ, рамзгузори SCSU, ки бастаи хуб истеҳсол мекунад, нисбат ба алгоритми ман мураккабтар ва душвортар хоҳад буд.

Барои муқоиса, ман татбиқи нисбатан соддаи SCSU-ро ба JavaScript интиқол додам - ​​аз рӯи ҳаҷми код он бо UTF-C-и ман муқоисашаванда буд, аммо дар баъзе ҳолатҳо натиҷа даҳҳо фоиз бадтар буд (баъзан он метавонад аз он зиёдтар бошад, аммо на зиёд). Масалан, матнҳои ибронӣ ва юнонӣ бо UTF-C рамзгузорӣ карда шуданд 60% беҳтар аз SCSU (шояд аз алифбои паймонашон бошад).

Алоҳида, ман илова мекунам, ки ба ғайр аз SCSU роҳи дигари ба таври компакт муаррифии Юникод мавҷуд аст - BOCU-1, аммо он барои мутобиқати MIME нигаронида шудааст (ки ба ман лозим набуд) ва барои рамзгузорӣ муносибати каме дигарро мегирад. Ман самаранокии онро баҳо надодаам, аммо ба назарам, аз SCSU баландтар буданаш гумон аст.

Такмилҳои имконпазир

Алгоритми пешниҳодкардаи ман аз рӯи тарҳ универсалӣ нест (эҳтимол дар ин ҷо ҳадафҳои ман аз ҳадафҳои Консорсиуми Юникод фарқ мекунанд). Ман қаблан зикр кардам, ки он асосан барои як вазифа (нигоҳ доштани луғати бисёрзабона дар дарахти префикс) таҳия шудааст ва баъзе хусусиятҳои он барои дигар вазифаҳо чандон мувофиқ нестанд. Аммо далели он, ки он стандарт нест, метавонад як плюс бошад - шумо метавонед онро ба осонӣ мувофиқи ниёзҳои худ тағир диҳед.

Масалан, ба таври возеҳ шумо метавонед аз мавҷудияти давлат халос шавед, рамзгузории бидуни шаҳрвандӣ анҷом диҳед - танҳо тағирёбандаҳоро нав накунед offs, auxOffs и is21Bit дар рамзгузор ва декодер. Дар ин ҳолат, ба таври муассир бастабандии пайдарпайии аломатҳои як алифбо имконнопазир хоҳад буд, аммо кафолат дода мешавад, ки ҳамон аломат, новобаста аз контекст, ҳамеша бо ҳамон байтҳо рамзгузорӣ карда мешавад.

Илова бар ин, шумо метавонед бо тағир додани ҳолати пешфарз рамзгузорро ба забони мушаххас мутобиқ кунед - масалан, тамаркуз ба матнҳои русӣ, рамзгузор ва декодерро дар ибтидо насб кунед offs = 0x0400 и auxOffs = 0. Ин махсусан дар ҳолати бе шаҳрвандӣ маъно дорад. Умуман, ин ба истифодаи рамзгузории ҳашт-битии кӯҳна монанд хоҳад буд, аммо бидуни аз байн бурдани қобилияти ворид кардани аломатҳо аз тамоми Юникод дар ҳолати зарурӣ.

Камбудии дигаре, ки дар боло зикр шуд, ин аст, ки дар матни калон, ки бо UTF-C рамзгузорӣ шудааст, роҳи зуд пайдо кардани сарҳади аломатҳои наздиктарин ба байтҳои ихтиёрӣ вуҷуд надорад. Агар шумо охирин, масалан, 100 байтро аз буфери рамзгузоришуда буред, шумо хавфи гирифтани ахлотро доред, ки бо он коре карда наметавонед. Рамзгузорӣ барои нигоҳ доштани гузоришҳои бисёр-гигабайтӣ пешбинӣ нашудааст, аммо дар маҷмӯъ инро метавон ислоҳ кард. Байт 0xBF набояд ҳеҷ гоҳ ҳамчун байти аввал пайдо шавад (вале метавонад дуюм ё сеюм бошад). Аз ин рӯ, ҳангоми рамзгузорӣ шумо метавонед пайдарпайро ворид кунед 0xBF 0xBF 0xBF ҳар як, масалан, 10 KB - пас, агар ба шумо сарҳад лозим шавад, скан кардани порчаи интихобшуда то пайдо шудани маркери шабеҳ кофӣ хоҳад буд. Аз паи охирин 0xBF кафолат дода мешавад, ки ибтидои характер. (Ҳангоми рамзкушоӣ, ин пайдарпаии се байт, албатта, бояд сарфи назар карда шавад.)

Барои ҷамъбаст кардан

Агар шумо то ин вақт хонда бошед, табрик! Умедворам, ки шумо низ мисли ман дар бораи сохтори Юникод чизи нав омӯхтед (ё хотираи худро тароват додед).

Дигар велосипед: мо сатрҳои Юникодро нисбат ба UTF-30 60-8% зичтар нигоҳ медорем
Саҳифаи намоишӣ. Мисоли забони ибрӣ бартариҳоро нисбат ба UTF-8 ва SCSU нишон медиҳад.

Тадқиқоти дар боло тавсифшуда набояд ҳамчун таҷовуз ба стандартҳо ҳисобида шавад. Бо вучуди ин ман умуман аз натичахои корам каноатмандам, бинобар ин аз онхо хурсандам ҳисса: масалан, китобхонаи хурдшудаи JS ҳамагӣ 1710 байт вазн дорад (ва албатта вобастагӣ надорад). Тавре ки ман дар боло зикр кардам, кори ӯро метавон дар ин ҷо пайдо кард саҳифаи намоишӣ (инчунин маҷмӯи матнҳо мавҷуданд, ки дар онҳо онро бо UTF-8 ва SCSU муқоиса кардан мумкин аст).

Дар ниҳоят, ман бори дигар таваҷҷӯҳро ба ҳолатҳое, ки дар онҳо UTF-C истифода мешавад, ҷалб мекунам на ба он:

  • Агар сатрҳои шумо кофӣ дароз бошанд (аз 100-200 аломат). Дар ин ҳолат, шумо бояд дар бораи истифодаи алгоритмҳои фишурдасозӣ, ба монанди deflate фикр кунед.
  • Агар лозим бошад Шаффофияти ASCII, яъне барои шумо муҳим аст, ки пайдарпайии рамзгузорӣ рамзҳои ASCII-ро дар бар нагиранд, ки дар сатри аслӣ набуданд. Зарурати инро метавон пешгирӣ кард, агар ҳангоми ҳамкорӣ бо API-ҳои тарафи сеюм (масалан, кор бо пойгоҳи додаҳо), шумо натиҷаи рамзгузориро ҳамчун маҷмӯи абстрактии байтҳо интиқол диҳед, на ҳамчун сатр. Дар акси ҳол, шумо хавфи осебпазирии ногаҳонӣ доред.
  • Агар шумо хоҳед, ки сарҳадҳои аломатҳоро бо ҷуброни худсарона зуд пайдо кунед (масалан, вақте ки як қисми сатр вайрон шудааст). Инро метавон анҷом дод, аммо танҳо тавассути скан кардани сатр аз аввал (ё татбиқи тағироте, ки дар боби қаблӣ тавсиф шудааст) анҷом дода мешавад.
  • Агар ба шумо лозим ояд, ки амалиётҳоро дар мундариҷаи сатрҳо зуд иҷро кунед (онҳоро ҷудо кунед, зерсатрҳоро дар онҳо ҷустуҷӯ кунед, пайваст кунед). Ин аввал рамзкушоӣ кардани сатрҳоро талаб мекунад, бинобар ин дар ин мавридҳо UTF-C нисбат ба UTF-8 сусттар мешавад (вале нисбат ба алгоритмҳои фишурда). Азбаски як сатр ҳамеша як хел рамзгузорӣ мешавад, муқоисаи дақиқи рамзкушоӣ талаб карда намешавад ва онро метавон дар асоси байт ба байт анҷом дод.

навсозии: истифодабаранда Тёмич дар шарҳҳои зер графикеро нашр кард, ки маҳдудиятҳои татбиқи UTF-C-ро нишон медиҳад. Он нишон медиҳад, ки UTF-C нисбат ба алгоритми фишурдани таъиноти умумӣ самараноктар аст (як варианти LZW), то даме ки сатри басташуда кӯтоҳтар аст ~ 140 аломат (Аммо, ман қайд мекунам, ки муқоиса дар як матн гузаронида шудааст; барои забонҳои дигар натиҷа метавонад фарқ кунад).
Дигар велосипед: мо сатрҳои Юникодро нисбат ба UTF-30 60-8% зичтар нигоҳ медорем

Манбаъ: will.com

Илова Эзоҳ