Sanyanggae LogoSanyanggae

💻 Web dan pembangunan frontend

Apakah beza Unicode dan UTF-8? Teks Korea rosak, bait, panjang rentetan dan penormalan

Bandingkan titik kod Hangul dan emoji, bait UTF-8 serta panjang rentetan JavaScript; bezakan penyahkodan salah, masalah fon, penormalan dan pemeliharaan teks asal.

사냥개 (Sanyanggae)Diterbitkan Dikemas kini 18 minit

Ini ialah terjemahan teks asal bahasa Korea. Teks asal bahasa Korea · Semakan terjemahan: Disemak oleh AI

Rajah tiga panel tentang aksara dan titik kod, bait UTF-8 serta paparan dan penormalan
Rajah penerangan oleh Sanyanggae yang membezakan nombor aksara Unicode, bait simpanan UTF-8 serta aturan paparan dan perbandingan. Bukan tangkap layar gangguan sebenar atau hasil ukuran.

1. Nombor aksara berbeza daripada bait simpanan

Bayangkan sebuah dokumen bahasa Korea dieksport dan dibuka semula, tetapi tajuknya kelihatan sebagai aksara pelik. Bahasa orang yang menaipnya tidak berubah; aturan membaca nombor yang disimpan mungkin tidak sepadan. Unicode ialah piawai yang memberikan nombor bernama titik kod kepada pelbagai aksara dan simbol, manakala UTF-8 ialah pengekodan yang mewakili nilainya sebagai urutan bait. Contohnya, suku kata Hangul ‘가’ mempunyai titik kod U+AC00. Bahagian selepas U+ ialah notasi perenambelasan, bukannya kedudukan dalam fail atau alamat ingatan. Nombor ini tidak menetapkan bentuk fon atau kedudukan piksel pada skrin. Titik kod yang sama juga boleh dilukis secara berbeza mengikut fon dan persekitaran susun atur. Oleh itu, sokongan Unicode, penyimpanan UTF-8 dan pemasangan fon Hangul saling berkaitan, tetapi setiap satunya perlu diperiksa. Penerangan UTF oleh Unicode membantu membezakan aksara daripada format penyimpanannya.

Dalam UTF-8, ‘가’ menjadi tiga bait perenambelasan EA B0 80. Sebaliknya, huruf A mempunyai titik kod U+0041 dan hanya menggunakan satu bait, 41, dalam UTF-8. Satu bait ialah lapan bit, jadi panjang bait bagi aksara berlainan dalam dokumen yang sama boleh berbeza. Sambungan .txt atau .csv sahaja juga tidak menentukan pengekodan sebenar. UTF-8 mewakili nilai skalar Unicode yang sah menggunakan satu hingga empat bait, maka saiz fail tidak dapat dikira tepat dengan hanya mendarab bilangan aksara yang kelihatan. Contoh suku kata Hangul ini juga tidak boleh digunakan untuk semua simbol berkaitan Hangul atau semua bahasa. Pengekodan ialah aturan menukar maklumat aksara kepada bait, bukannya pemampatan atau penyulitan. Saiz keseluruhan ayat yang sama mungkin berbeza kerana maklumat tambahan format fail, baris baharu atau pemampatan penghantaran. Dengan memisahkan penukaran bait dan aksara yang ditakrifkan dalam WHATWG Encoding Standard daripada saiz keseluruhan fail dan fungsi kerahsiaan, masalah dapat dikecilkan skopnya.

2. Bilangan bait, unit kod dan aksara yang kelihatan

Dalam JavaScript, length bagi rentetan memberikan bilangan unit kod UTF-16. Nilai ini bukan bilangan bait fail UTF-8 atau bilangan aksara menurut persepsi manusia. Wajah tersenyum ‘😀’, misalnya, mempunyai satu titik kod U+1F600 tetapi dua unit kod UTF-16, jadi '😀'.length ialah 2. Hasil pengekodan UTF-8 ialah F0 9F 98 80, iaitu empat bait. Nombor perpuluhan 128512 yang diperoleh melalui codePointAt(0) ialah nombor yang sama dengan U+1F600, bukannya bilangan aksara atau saiz fail. Mengikut ketiga-tiga ukuran itu, ‘가’ mempunyai satu titik kod, satu unit kod UTF-16 dan tiga bait UTF-8. Nombor bagi rentetan yang sama berbeza kerana unitnya berbeza. Penerangan panjang rentetan di MDN menyatakan unit length. Nilai ini sahaja juga tidak dapat memastikan bilangan bait ingatan yang sebenarnya digunakan oleh enjin JavaScript.

Mengira titik kod satu demi satu juga tidak semestinya sama dengan bilangan aksara yang dilihat pengguna. Aksara asas boleh disertai tanda gabungan, dan beberapa titik kod boleh membentuk satu emoji. Aturan pembahagian teks Unicode menerangkan sempadan kelompok grafem lanjutan untuk menangani gabungan ini. Mengembangkan rentetan mengikut titik kod dengan Array.from(text) juga tidak secara automatik mengira gabungan beberapa titik kod sebagai satu kelompok. Untuk mengiranya dalam pelayar, periksa sokongan persekitaran sebelum mempertimbangkan Intl.Segmenter dengan granularity ditetapkan kepada 'grapheme'. Namun, kelompok grafem tidak dijamin sepadan satu dengan satu dengan satu gambar yang dilukis fon, dan jangkaan penyuntingan boleh berbeza mengikut bahasa. Ruang pengenalan diri patut menggunakan bilangan aksara yang difahami pengguna, manakala had storan dan komunikasi menggunakan bilangan bait secara berasingan. Antara muka yang menyatakan ‘20 aksara’ tetapi memotong hanya mengikut unit kod UTF-16 boleh memutuskan emoji atau aksara gabungan di tengah.

3. Bezakan penyimpanan, penghantaran dan paparan apabila teks rosak

Kerosakan aksara boleh berlaku apabila pengekodan semasa menulis bait berbeza daripada penyahkodan semasa membacanya. Fail yang disimpan dalam UTF-8 tetapi ditafsir sebagai pengekodan lain boleh memaparkan aksara salah walaupun fail itu sendiri tidak berubah. Dalam HTML, semak format simpanan sebenar, charset dalam Content-Type respons HTTP dan pengisytiharan meta charset pada awal dokumen bersama-sama. Atribut HTML lang='ko' menyatakan bahasa kandungan; peranannya berbeza daripada charset yang menentukan cara membaca bait Hangul. Panduan pengisytiharan pengekodan W3C menerangkan bahawa menukar pengisytiharan kepada UTF-8 perlu disertai penyimpanan fail sebenar dalam UTF-8, serta padanan pengisytiharan pelayan dan dokumen. Penanda pengekodan juga boleh mempengaruhi keutamaan penentuan, jadi satu meta tidak semestinya mengatasi semua maklumat lain. Jika membuka fail terus memberikan hasil berbeza daripada akses melalui pelayan, tetapan penghantaran menjadi petunjuk penting.

Fon yang tidak mempunyai bentuk aksara diperlukan boleh menghasilkan kotak, dan puncanya mungkin berbeza daripada penyahkodan salah. Jika data aksara betul tetapi bentuknya tidak tersedia, menukar pengekodan simpanan tidak menyelesaikannya. Sebaliknya, fon baharu tidak mengembalikan aksara asal yang sudah ditafsir sebagai aksara lain. Semasa menyiasat, simpan salinan fail bermasalah dan bandingkan pengekodan pilihan penyunting, pengisytiharan respons pelayan, aksara yang ditafsir pelayar dan fon yang digunakan. Jangan tetapkan punca berdasarkan rupa sahaja; periksa titik kod yang diperoleh apabila bahagian sama disalin. Catat sama ada masalah hanya berlaku dalam pelayar tertentu dan sama ada penyunting lain juga salah membaca fail yang sama, bagi membezakan masalah paparan daripada perubahan data. Menyimpan berulang kali sehingga aksara nampak betul boleh menghilangkan bait asal. Jika semua pengisytiharan halaman betul tetapi hanya satu tulisan bermasalah, teliti juga tahap perubahan sebelum kandungannya dimasukkan ke pangkalan data.

4. Menyemak nilai yang sama dengan TextEncoder dan TextDecoder

Mulakan eksperimen mudah dengan rentetan pendek yang dibuat sendiri. TextEncoder menukar rentetan JavaScript kepada tatasusunan bait UTF-8. Hasil new TextEncoder().encode('가') dalam perenambelasan ialah EA B0 80, dan length tatasusunan ialah 3. Alat pembangun mungkin memaparkan nilai perpuluhan 234, 176, 128; itu bukan data berlainan, hanya asas nombor yang berbeza. Bandingkan dengan length biasa rentetan yang bernilai 1 untuk melihat perbezaan unit. Membaca tatasusunan itu menggunakan new TextDecoder('utf-8').decode(bytes) menghasilkan ‘가’; bytes merujuk tatasusunan bait yang dibuat tadi. Pengekod ini menghasilkan UTF-8, bukannya penukar serba guna untuk menyimpan dalam sebarang pengekodan lama pilihan kita. Apabila menyiasat fail sebenar, gunakan bait asal yang diperoleh terlebih dahulu. Mengekodkan semula ayat pada skrin yang sudah tersalah baca kepada UTF-8 tidak membuktikan bait yang terdapat dalam fail awal.

Menetapkan 'utf-8' dan { fatal: true } dalam pembina TextDecoder menyebabkan input yang tidak mematuhi aturan dianggap ralat, bukannya diganti secara senyap. Contohnya, satu bait FF bukan input UTF-8 yang sah, maka penyahkodan dalam mod ini gagal. Dalam mod penggantian lalai, bahagian salah boleh menjadi aksara pengganti U+FFFD. Namun, ketiadaan ralat bukan bukti bahawa pengekodan asal sudah dikenal pasti atau kandungan dipastikan betul. Sesetengah bait bertindih antara pengekodan, dan hasil yang sudah bertukar menjadi aksara lain mungkin disimpan semula sebagai UTF-8 yang sah. Semakan ini memastikan sama ada penyahkod pilihan boleh menerima input. Ia tidak secara automatik mengesahkan sumber dokumen, kesepadanan dengan teks asal atau sama ada fail diubah semasa perjalanan.

5. Penormalan menyelaraskan perwakilan melalui proses berasingan

Dua rentetan yang dibaca dengan betul juga boleh mempunyai urutan titik kod berbeza. ‘가’ boleh diwakili oleh satu U+AC00 atau urutan jamo awal penggabung U+1100 dan jamo vokal U+1161. Dua nilai terakhir berbeza daripada contoh yang sekadar meletakkan jamo keserasian harian ‘ㄱ’ dan ‘ㅏ’ bersebelahan, maka nombornya perlu disemak bersama. Kedua-dua perwakilan biasanya dilukis sebagai suku kata yang sama, tetapi perbandingan rentetan mentah JavaScript mungkin menganggapnya tidak sama. Menggunakan NFC berdasarkan aturan penormalan Unicode pada kedua-duanya membolehkan contoh yang setara secara kanonik ini dibandingkan dalam perwakilan sama. NFD menggunakan penguraian kanonik. Dalam contoh ini, perwakilan UTF-8 NFC ialah tiga bait, manakala dua jamo NFD ialah enam bait; paparan sama boleh mempunyai saiz storan berbeza. Jika istilah carian dan nama tersimpan kelihatan sama tetapi tidak sepadan, perbezaan perwakilan ini boleh disiasat, berasingan daripada kerosakan aksara akibat tafsiran bait yang salah.

Bentuk penormalan juga dipilih mengikut tujuan. NFC menangani kesetaraan kanonik, manakala NFKC melibatkan penguraian keserasian yang boleh mengubah perwakilan input secara lebih luas, termasuk angka lebar penuh atau angka berbulatan yang asalnya berbeza. Ini boleh membantu menghasilkan nilai pembanding untuk carian, tetapi perbezaannya mungkin bermakna dalam notasi matematik atau bahan asal. Oleh itu, simpan nilai asal dan tentukan bentuk yang digunakan pada salinan perbandingan yang diperlukan. Penormalan tidak menggantikan perbandingan huruf besar-kecil, pengisihan mengikut bahasa atau pencarian perkataan yang sama bunyinya. Penukaran pukal nama fail atau pengecam akaun sedia ada boleh menyatukan entri berbeza kepada nilai pembanding sama, jadi aturan penamaan perkhidmatan dan pengendalian pertembungan perlu dikaji terlebih dahulu. Menyimpan semua aksara yang kelihatan serupa sebagai nilai sama bukan tujuan umum penormalan.

6. Simpan teks asal dan catat sempadan penukaran

Semasa mengecilkan skop punca kerosakan, simpan bait asal dan catatan asal perolehan sebelum menulis ganti fail awal. Cuba baca salinan menggunakan pengekodan yang dijangka, kemudian semak sama ada kandungan kekal sama selepas hasil yang kelihatan betul disimpan semula. Penanda awal UTF-8 dalam penerangan BOM W3C ialah EF BB BF, tetapi bait tersebut tidak wajib. UTF-8 tidak memerlukan pemilihan susunan bait, jadi penanda ini tidak patut difahami sebagai pemilih susunan bait seperti dalam UTF-16. Menambah atau membuang BOM juga berbeza daripada menukar bait kandungan kepada pengekodan lain. Jika nilai yang tidak dapat dibaca telah disimpan sebagai aksara pengganti atau tanda soal, beberapa nilai asal mungkin sudah bergabung menjadi satu, maka pemulihan automatik tidak boleh dijamin. Kemungkinan membalikkan perubahan hanya boleh dinilai setelah pengekodan asal dan sejarah penukaran diketahui. Penormalan bukan alat memulihkan bait yang hilang.

Apabila membina ciri berbilang bahasa, jangan tamatkan semakan dengan satu baris bahasa Inggeris sahaja. Masukkan suku kata Hangul, huruf Latin bertanda gabungan, emoji satah tambahan dan tulisan kanan-ke-kiri seperti Arab atau Ibrani dalam himpunan ayat pendek yang sama, kemudian bandingkan input, penyimpanan, bacaan semula dan eksport. Pada setiap tahap, semak rupa paparan, titik kod, bilangan bait UTF-8 dan piawai bilangan aksara yang ditetapkan produk. Arah tulisan bukan sifat yang diselesaikan dengan menukar UTF-8 kepada pengekodan lain; bahasa dan tetapan arah antara muka juga perlu disemak berasingan. Apabila mengubah had input atau perbandingan carian, kekalkan teks asal dan jelaskan piawai yang berubah. Pastikan nombor panduan dalam pelayar dan had penerimaan pelayan memakai unit sama; jika had berlainan diperlukan, nyatakan setiap satunya. Angka dan kod dalam tulisan ini menunjukkan penukaran rentetan contoh pendek, bukannya ukuran gangguan perkhidmatan tertentu. Dengan menyemak nombor aksara, bait simpanan, unit rentetan serta aturan paparan dan perbandingan secara berturutan, perubahan pada setiap sempadan dapat dihasilkan semula.

Sumber dan bacaan lanjut

Artikel ini menerangkan maklumat daripada sumber awam. Petikan sumber tidak bermakna organisasi berkenaan menyemak atau mengesahkannya.

Penerbit dan hubungan

Artikel lain tentang topik ini