Unicode va UTF-8: kodirovkalar qanday ishlaydi va matn nega buziladi
Amaliyot3 daqInnovialabs tahririyati
Qisqacha
Unicode har bir belgiga raqam beradi, UTF-8 esa bu raqamni 1–4 baytga aylantiradi. Matn baytlar bir kodirovkada yozilib, boshqasida o‘qilganda buziladi — shuning uchun hamma joyda UTF-8 ni aniq ko‘rsating.
Qisqacha: buzilgan matn qayerdan paydo bo‘ladi
Kompyuter harflarni emas, baytlarni saqlaydi. Kodirovka — baytlarni belgilarga aylantirish qoidasi. Agar matn bir kodirovkada saqlanib, boshqasida ochilsa, ruscha «Привет» o‘rniga «РџСЂРёРІРµС‚» ko‘rinadi. Bu mojibake deb ataladi.
Yechim deyarli har doim bitta: hamma joyda UTF-8 dan foydalaning va o‘qish hamda yozishda kodirovkani aniq ko‘rsating.
Unicode, kod nuqtalari va UTF-8
- Unicode — har bir belgi o‘z raqamiga, ya’ni kod nuqtasiga ega bo‘lgan katta jadval. Kirillcha «А» —
U+0410, lotinchaa—U+0061, o‘ dagi ‘ belgisi —U+2018. - UTF-8 — kod nuqtasini baytlar bilan yozish usuli. Lotin harflari 1 bayt, kirill harflari 2 bayt, ko‘plab tinish belgilari va simvollar 3 bayt, emoji 4 bayt egallaydi.
| Belgi | Kod nuqtasi | UTF-8 baytlari |
|---|---|---|
a | U+0061 | 61 |
А (kirill) | U+0410 | D0 90 |
‘ | U+2018 | E2 80 98 |
Windows-1251 — kirill uchun eski bir baytli kodirovka. Unda «А» bitta C0 bayti. U hali ham eski tizimlardan eksportlarda, Excel CSV fayllarida va eskirgan bazalarda uchraydi.
Buzilish qanday yuz beradi
«П» harfini olaylik: UTF-8 da bu D0 9F baytlari. Faylni Windows-1251 deb hisoblaydigan dastur ikkita alohida belgini ko‘radi: D0 — «Р», 9F — «џ». Buzilgan so‘z boshidagi «Рџ» shundan.
Teskari holat: Windows-1251 dagi fayl UTF-8 sifatida ochilgan. Bu baytlar to‘g‘ri ketma-ketlik hosil qilmaydi va matn o‘rniga � belgilari chiqadi.
Amalda qanday tuzatish kerak
Fayllarni aniq kodirovka bilan o‘qing va yozing:
with open("data.csv", encoding="utf-8") as f:
text = f.read()
Eski fayllarni konvertatsiya qiling:
iconv -f WINDOWS-1251 -t UTF-8 old.csv > new.csv
Allaqachon buzilgan satrni tuzating, agar u qanday buzilganini bilsangiz:
broken = "Привет"
fixed = broken.encode("cp1251").decode("utf-8") # "Привет"
Har bir qatlamni tekshiring:
- HTML:
<meta charset="utf-8">vaContent-Type: text/html; charset=utf-8sarlavhasi. - MySQL:
utf8emas,utf8mb4kodirovkasi —utf8ko‘pi bilan 3 bayt saqlaydi va emojini qabul qilmaydi. - PostgreSQL:
UTF8kodirovkadagi baza. - Excel uchun CSV: BOM bilan UTF-8 da saqlang (Python’da
encoding="utf-8-sig"), aks holda Excel kirillni noto‘g‘ri ochishi mumkin. - Kod muharriri va Git: fayllar UTF-8 da.
O‘zbekcha o‘ va g‘: alohida tuzoq
o‘, g‘ dagi va ma’lumot kabi so‘zlardagi belgini turli simvollar bilan terish mumkin: ' (U+0027), ` (U+0060), ‘ (U+2018), ’ (U+2019), ʻ (U+02BB). Ular tashqi ko‘rinishda o‘xshash, lekin kompyuter uchun turli belgilar. Oqibatlari:
- «o‘zbek» bo‘yicha qidiruv boshqa belgi bilan yozilgan variantni topmaydi;
- ma’lumotnomalar, mijozlar va manzillarda dublikatlar;
- bitta so‘z uchun turli URL va slug’lar.
Nima qilish kerak: loyiha uchun bitta variantni tanlang va saqlashda kiritilgan ma’lumotni normallashtiring — boshqa variantlarni tanlanganiga almashtiring. Qidiruv uchun qo‘shimcha normallashtirilgan maydon saqlang.
Yana bir nozik jihat — satr uzunligi. "o‘" — 2 ta kod nuqtasi, lekin UTF-8 da 4 bayt. Agar bazadagi maydon belgilar emas, baytlar bilan cheklangan bo‘lsa, matn belgi o‘rtasida kesilib qolishi mumkin.
Unicode normallashtirish
Ba’zi harflarni ikki usulda yozish mumkin: «й» — bitta kod nuqtasi yoki «и» va qo‘shiladigan belgi. Ko‘rinishi bir xil, lekin satrlarni solishtirish False beradi. Matnni bitta shaklga keltiring:
import unicodedata
clean = unicodedata.normalize("NFC", text)