بل بایسکل: موږ د یونیکوډ تارونه د UTF-30 په پرتله 60-8٪ ډیر کمپیکٹ ذخیره کوو

بل بایسکل: موږ د یونیکوډ تارونه د UTF-30 په پرتله 60-8٪ ډیر کمپیکٹ ذخیره کوو

که تاسو پراختیا کونکی یاست او تاسو د کوډ کولو غوره کولو دندې سره مخ یاست ، نو یونیکوډ به نږدې تل سم حل وي. د ځانګړي نمایش میتود په شرایطو پورې اړه لري، مګر ډیری وختونه دلته یو نړیوال ځواب شتون لري - UTF-8. د دې په اړه ښه شی دا دی چې دا تاسو ته اجازه درکوي پرته له لګښت څخه ټول یونیکوډ حروف وکاروئ هم په ډیری قضیو کې ډیری بایټونه. ریښتیا، د هغو ژبو لپاره چې یوازې د لاتیني الفبا څخه ډیر کاروي، "ډیر نه" لږترلږه په هر کرکټر دوه بایټ. ایا موږ کولی شو پرته له دې چې مخکې تاریخي کوډونو ته بیرته راستون شو چې موږ یوازې 256 موجود حروف ته محدود کړو؟

لاندې زه وړاندیز کوم چې دې پوښتنې ته د ځواب ویلو لپاره زما د هڅې سره ځان وپیژنم او یو نسبتا ساده الګوریتم پلي کړم چې تاسو ته اجازه درکوي د نړۍ په ډیری ژبو کې لاینونه ذخیره کړئ پرته لدې چې په UTF-8 کې شتون لري اضافه کړئ.

ردول. زه به سمدلاسه یو څو مهم ریزورډونه وکړم: تشریح شوی حل د UTF-8 لپاره د نړیوال بدیل په توګه نه وړاندیز کیږي، دا یوازې د قضیو په محدود لیست کې مناسب دی (د دوی لاندې نور) ، او په هیڅ حالت کې باید دا د دریمې ډلې APIs سره متقابل عمل کولو لپاره ونه کارول شي (څوک چې حتی پدې اړه نه پوهیږي). ډیری وختونه، د عمومي هدف کمپریشن الګوریتمونه (د بیلګې په توګه، ډیفلیټ) د متن ډیټا لوی مقدار د کمپیکٹ ذخیره کولو لپاره مناسب دي. سربیره پردې ، دمخه زما د حل رامینځته کولو په پروسه کې ، ما پخپله یونیکوډ کې یو موجود معیار وموند ، کوم چې ورته ستونزه حل کوي - دا یو څه ډیر پیچلی دی (او ډیری وختونه بدتر) ، مګر بیا هم دا یو منل شوی معیار دی ، او نه یوازې دا. یوځای په زنګون. زه به تاسو ته د هغه په ​​اړه هم ووایم.

د یونیکوډ او UTF-8 په اړه

د پیل لپاره، د هغه څه په اړه یو څو کلمې یونیسیډ и UTF-8.

لکه څنګه چې تاسو پوهیږئ، 8-bit کوډونه مشهور وو. د دوی سره، هرڅه ساده وو: 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، او نه چینایي او نه هم د مثال په توګه ، جورجیا پدې کې شامل دي. سیریلیک او پنځه نور الفبا - hurray - بختور، په هر کریکټر کې 2 بایټ.

ولې داسې کیږي؟ راځئ وګورو چې UTF-8 څنګه د کرکټر کوډونو استازیتوب کوي:
بل بایسکل: موږ د یونیکوډ تارونه د UTF-30 په پرتله 60-8٪ ډیر کمپیکٹ ذخیره کوو
په مستقیم ډول د شمیرو ښودلو لپاره، د سمبول سره نښه شوي بټونه دلته کارول کیږي x. دا لیدل کیدی شي چې په دوه بایټ ریکارډ کې یوازې 11 داسې بټونه شتون لري (له 16 څخه). دلته مخکښ بټونه یوازې یو مرستندویه فعالیت لري. د څلور بایټ ریکارډ په حالت کې، د 21 بټونو څخه 32 د کوډ پوائنټ نمبر لپاره تخصیص شوي - داسې ښکاري چې درې بایټونه (کوم چې ټول 24 بټونه ورکوي) به کافي وي، مګر د خدماتو نښه کونکي خورا ډیر خوري.

ایا دا بد دی؟ واقعیآ نه. له یوې خوا، که موږ د ځای په اړه ډیره پاملرنه کوو، موږ د کمپریشن الګوریتمونه لرو چې کولی شي په اسانۍ سره ټول اضافي انټروپي او بې ځایه له منځه یوسو. له بلې خوا، د یونیکوډ هدف د امکان تر ټولو نړیوال کوډینګ چمتو کول وو. د مثال په توګه، موږ کولی شو په UTF-8 کې کوډ شوی کرښه کوډ ته وسپارو چې مخکې یې یوازې د ASCII سره کار کاوه، او ویره مه کوئ چې دا به د ASCII رینج څخه یو کرکټر وګوري چې واقعیا شتون نلري (په هرصورت، په UTF-8 کې ټول بایټونه د صفر بټ څخه پیل کیږي - دا هغه څه دي چې ASCII دی). او که موږ ناڅاپه وغواړو چې له پیل څخه د کوډ کولو پرته د لوی تار څخه یو کوچنی لکۍ پرې کړو (یا د خرابې شوې برخې وروسته د معلوماتو برخه بحال کړو) ، نو دا زموږ لپاره اسانه ده چې آفسټ ومومئ چیرې چې یو کرکټر پیل کیږي (دا بس دی) د بایټونو پریښودو لپاره چې یو څه مخکینۍ لري 10).

نو ولې یو څه نوی اختراع کړو؟

په ورته وخت کې، ځینې وختونه داسې شرایط شتون لري کله چې د کمپریشن الګوریتمونه لکه ډیفلیټ په کمزوري ډول پلي کیږي، مګر تاسو غواړئ د تارونو کمپیکٹ ذخیره ترلاسه کړئ. په شخصي توګه، زه د دې ستونزې سره مخ شوم کله چې د جوړولو په اړه فکر کوم compressed prefix ونه د لوی قاموس لپاره په خپل سري ژبو کې د کلمو په شمول. له یوې خوا، هره کلمه خورا لنډه ده، نو د هغې فشارول به بې اغیزې وي. له بلې خوا، د ونې پلي کول چې ما په پام کې نیولي و ډیزاین شوي ترڅو د ذخیره شوي تار هر بایټ د ونې جلا عمودی تولید کړي، نو د دوی شمیر کمول خورا ګټور و. زما په کتابتون کې Az.js (لکه په pymorphy2، په کوم باندې چې دا پراساس دی) ورته ستونزه په ساده ډول حل کیدی شي - تارونه په کې بسته شوي DAWG- قاموس، هلته ذخیره شوی ښه زوړ CP1251. مګر، لکه څنګه چې پوهیدل اسانه دي، دا یوازې د محدود الفبا لپاره ښه کار کوي - په چینایي کې یوه کرښه په داسې لغت کې نشي اضافه کیدی.

په جلا توګه، زه غواړم یو بل ناخوښۍ یادونه وکړم چې د داسې ډیټا جوړښت کې د UTF-8 کارولو په وخت کې رامینځته کیږي. پورتني انځور ښیي چې کله یو کرکټر د دوه بایټونو په توګه لیکل کیږي، د هغې شمیرې پورې اړوند بټونه په قطار کې نه راځي، بلکې د یوې جوړې بټونو په واسطه جلا کیږي. 10 په منځ کې: 110xxxxx 10xxxxxx. د دې له امله، کله چې د دویم بایټ ټیټ 6 بټونه د کرکټر کوډ کې تیریږي (د بیلګې په توګه، لیږد واقع کیږي 1011111110000000)، بیا لومړی بایټ هم بدلیږي. دا معلومه شوه چې د "p" لیک د بایټ په واسطه ښودل شوی 0xD0 0xBF، او راتلونکی "r" لا دمخه دی 0xD1 0x80. په یوه مخکیني ونې کې، دا د اصلي نوډ دوه برخو ویشلو لامل کیږي - یو د مخکیني لپاره 0xD0، او بل لپاره 0xD1 (که څه هم ټول سیریلیک الفبا یوازې د دوهم بایټ لخوا کوډ کیدی شي).

ما څه ترلاسه کړل

د دې ستونزې سره مخ ، ما پریکړه وکړه چې د بټونو سره لوبې تمرین کړم ، او په ورته وخت کې د یونیکوډ جوړښت سره یو څه ښه آشنا شوم. پایله د UTF-C کوډ کولو بڼه وه ("C" لپاره تړون) ، کوم چې په هر کوډ نقطه کې له 3 بایټس څخه ډیر نه مصرفوي ، او ډیری وختونه تاسو ته اجازه درکوي یوازې مصرف کړئ د ټولې کوډ شوي کرښې لپاره یو اضافي بایټ. دا د دې حقیقت لامل کیږي چې په ډیری غیر ASCII الفبا کې دا ډول کوډ کول رامینځته کیږي د UTF-30 په پرتله 60-8٪ ډیر کمپیکٹ.

ما په فورمه کې د کوډ کولو او کوډ کولو الګوریتم پلي کولو مثالونه وړاندې کړل جاواسکریپټ او ګو کتابتونونه، تاسو کولی شئ په آزاده توګه دا په خپل کوډ کې وکاروئ. مګر زه به بیا هم ټینګار وکړم چې په یوه معنی کې دا بڼه یو "بایسکل" پاتې کیږي، او زه یې د کارولو وړاندیز نه کوم. پرته له دې چې پوه شي چې ولې ورته اړتیا لرئ. دا لاهم د جدي "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 (یعنې موږ ټول بټونه په یاد لرو پرته له لږ مهم څخه زینکس بکس);
  2. یو بایټ 0xxxxxxx دا د اوسني الفبا کرکټر دی. دا یوازې په هغه آفسیټ کې اضافه کولو ته اړتیا لري چې موږ په 1 مرحله کې یادونه کړې. په داسې حال کې چې موږ الفبا بدل نه کړ، آفسیټ صفر دی، نو موږ د ASCII سره مطابقت ساتلی.

په ورته ډول د کوډونو لپاره چې 3 بایټ ته اړتیا لري:

  1. درې بایټس 110yyyyy yxxxxxxx xxxxxxxx د یو شمیر سره سمبول په ګوته کړئ yyyyyy yxxxxxxx xxxxxxxx، بدلون اوسنی الفبا په yyyyyy y0000000 00000000 (د کوچنيانو پرته هر څه په یاد دي زینکس بکس)، او هغه بکس چیک کړئ چې موږ اوس په کې یو اوږد حالت (کله چې الفبا بیرته دوه بایټ ته بدل کړئ ، موږ به دا بیرغ بیا تنظیم کړو)؛
  2. دوه بایټس 0xxxxxxx xxxxxxxx په اوږد حالت کې دا د اوسني الفبا کرکټر دی. په ورته ډول، موږ دا د 1 مرحلې څخه د آفسټ سره اضافه کوو. یوازینی توپیر دا دی چې اوس موږ دوه بایټونه لوستلو (ځکه چې موږ دې حالت ته تیر شو).

ښه ښکاري: اوس پداسې حال کې چې موږ اړتیا لرو د ورته 7-bit یونیکوډ رینج څخه حروف کوډ کړو، موږ په پیل کې 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 څخه سیریلیک ته واړوو - سټیش اوس 64 حروف لري لاتیني الفبا، شمیرې، ځای او کوما (په غیر ASCII متنونو کې ډیری وختونه داخلول). بیرته ASCII ته لاړشئ - او د سیریلیک الفبا اصلي برخه به معاون الفبا شي.

دوه الفبا ته د لاسرسي څخه مننه ، موږ کولی شو د الفبا بدلولو لپاره لږترلږه لګښتونو سره ډیری متنونه اداره کړو (مقررې به ډیری وختونه ASCII ته بیرته راستنیدو لامل شي ، مګر له هغې وروسته به موږ د اضافي الفبا څخه ډیری غیر ASCII حروف ترلاسه کړو، پرته له دې چې بیا بدلول).

بونس: د فرعي الفبا مخکینی کول 11xxxxxx او د دې لپاره د دې ابتدايي آفسیټ غوره کول 0xC0، موږ د CP1252 سره جزوي مطابقت ترلاسه کوو. په بل عبارت، ډیری (مګر ټول نه) په CP1252 کې کوډ شوي لویدیځ اروپا متنونه به په UTF-C کې ورته ښکاري.

په هرصورت، دلته یو مشکل رامینځته کیږي: څنګه د اصلي الفبا څخه یو معاون ترلاسه کول؟ تاسو کولی شئ ورته آفسیټ پریږدئ ، مګر - افسوس - دلته د یونیکوډ جوړښت دمخه زموږ په وړاندې لوبه کوي. ډیری وختونه د الفبا اصلي برخه د بلاک په پیل کې نه وي (د بیلګې په توګه، د روسیې پلازمینه "A" کوډ لري 0x0410که څه هم د سیریلیک بلاک سره پیل کیږي 0x0400). په دې توګه، د لومړي 64 حروف په سټیش کې اخیستل، موږ ممکن د الفبا پای برخې ته لاسرسی له لاسه ورکړو.

د دې ستونزې د حل کولو لپاره، ما په لاسي ډول د مختلفو ژبو سره په مطابقت کې ځینې بلاکونو ته لاړم، او د دوی لپاره د اصلي الفبا کې د معاون الفبا آف سیٹ مشخص کړ. لاتیني الفبا، د استثنا په توګه، عموما د بیس 64 په څیر تنظیم شوی و.

بل بایسکل: موږ د یونیکوډ تارونه د 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 نسبتا ساده پلي کول جاواسکریپټ ته لیږدول - د کوډ حجم له مخې دا زما د UTF-C سره پرتله کولو وړ وګرځید ، مګر په ځینو مواردو کې پایله یې لس سلنه خرابه وه (کله ناکله دا ممکن له دې څخه ډیر شي ، مګر ډیر نه). د مثال په توګه، په عبراني او یوناني متنونه د UTF-C لخوا کوډ شوي د SCSU په پرتله 60٪ ښه (شاید د دوی د کمپیکٹ الفبا له امله).

په جلا توګه ، زه به دا اضافه کړم چې د 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 کوډونه نلري چې په اصلي تار کې ندي. د دې اړتیا مخنیوی کیدی شي که چیرې ، کله چې د دریمې ډلې APIs سره متقابل عمل وکړئ (د مثال په توګه ، د ډیټابیس سره کار کول) ، تاسو د کوډ کولو پایله د بایټس خلاصې سیټ په توګه تیر کړئ ، نه د تارونو په توګه. که نه نو، تاسو د غیر متوقع زیانونو د ترلاسه کولو خطر لرئ.
  • که تاسو غواړئ په خپل سري آفسیټ کې د کرکټر حدود په چټکۍ سره ومومئ (د مثال په توګه، کله چې د کرښې یوه برخه زیانمنه شوې وي). دا ترسره کیدی شي، مګر یوازې د پیل څخه د کرښې سکین کولو سره (یا په تیرو برخه کې تشریح شوي تعدیل پلي کول).
  • که تاسو اړتیا لرئ په چټکۍ سره د تارونو مینځپانګې باندې عملیات ترسره کړئ (دوی ترتیب کړئ ، په دوی کې فرعي سټرینګونه وپلټئ ، یوځای کړئ). دا اړتیا لري چې تارونه لومړی ډیکوډ شي، نو په دې قضیو کې UTF-C به د UTF-8 څخه ورو وي (مګر د کمپریشن الګوریتمونو څخه ګړندی). څرنګه چې ورته تار تل په ورته ډول کوډ شوی وي، د کوډ کولو دقیق پرتله کول اړین ندي او د بایټ په واسطه ترسره کیدی شي.

تازه معلومات: کارن تیومیتچ په لاندې نظرونو کې یو ګراف پوسټ کړی چې د UTF-C د پلي کیدو محدودیتونه په ګوته کوي. دا ښیې چې UTF-C د عمومي هدف کمپریشن الګوریتم (د LZW یو تغیر) څخه ډیر اغیزمن دی تر هغه چې بسته شوي تار لنډ وي. ~140 حروف (په هرصورت، زه یادونه کوم چې پرتله کول په یوه متن کې ترسره شوي؛ د نورو ژبو لپاره پایله ممکن توپیر ولري).
بل بایسکل: موږ د یونیکوډ تارونه د UTF-30 په پرتله 60-8٪ ډیر کمپیکٹ ذخیره کوو

سرچینه: www.habr.com

Add a comment