Apa yang dihitung sebagai satu karakter?
Empat sistem berbeda menghitung teks yang sama dengan empat cara berbeda. Untuk teks bahasa Inggris biasa hasilnya sama, dan karena itulah masalahnya tidak terlihat — sampai suatu hari terlihat.
Terakhir ditinjau
Satu emoji, empat jawaban
Ambil emoji jempol dengan warna kulit tertentu, atau emoji keluarga. Hitung dengan empat cara dan Anda mendapat empat angka, dan tidak satu pun yang salah.
Pembaca melihat satu karakter. Satu benda, satu kali tekan tombol backspace untuk menghapusnya.
Regular expression mungkin melihat tujuh. Emoji itu dibangun dari beberapa code point yang disambung oleh penghubung tak terlihat — emoji dasar, modifier, joiner, emoji lain, dan seterusnya.
JavaScript melaporkan sebelas. JavaScript menyimpan teks dalam unit 16-bit, dan apa pun di luar rentang dasar memakan dua unit, sehingga setiap code point itu bisa terhitung dua kali.
Kolom database melihat dua puluh lima byte. Saat di-encode sebagai UTF-8 untuk disimpan, setiap code point memakan hingga empat byte.
Untuk teks bahasa Inggris biasa, keempat angka itu identik. Justru karena itulah masalahnya tidak terlihat sampai seseorang memasukkan nama dengan aksen, kalimat dalam bahasa Jepang, atau satu emoji saja — dan kolom yang sudah berjalan lancar selama tiga tahun mulai memotong data.
Angka mana yang dimaksud batas Anda
Pertanyaan praktisnya tidak pernah “seberapa panjang teks ini”. Pertanyaannya adalah “apa yang membatasi”, dan ada empat jawaban yang umum.
Kolom database yang dideklarasikan sebagai VARCHAR menghitung byte di sebagian besar engine. Karena itulah kolom yang dengan mudah menerima 255 karakter bahasa Inggris menolak jauh lebih sedikit karakter Jepang — tiga byte per karakter — dan mengapa nama dengan aksen kadang tidak muat padahal versi tanpa aksennya muat.
SMS berisi 160 karakter dalam alfabet tujuh-bit miliknya sendiri, dan turun menjadi 70 per pesan begitu ada satu karakter di luar alfabet itu. Satu tanda kutip melengkung yang ditempel dari pengolah kata, atau satu emoji, bisa mengubah pesan satu bagian menjadi tiga bagian dan melipatgandakan biaya Anda tiga kali.
Validator formulir di JavaScript hampir selalu menghitung unit UTF-16, dan karena itulah kolom bertuliskan 280 karakter bisa menolak teks yang tampak jauh lebih pendek jika penuh emoji.
Manusia menghitung apa yang bisa dilihatnya, dan hanya definisi itulah yang penting untuk judul, title tag, atau apa pun yang punya batas ruang visual.
Di mana hasil hitungannya berbeda
Mengetahui input mana yang menimbulkan masalah lebih berguna daripada memahami teorinya, karena input-input itu bisa ditebak.
Emoji, terutama emoji gabungan — warna kulit, keluarga, bendera, profesi. Bendera terdiri dari dua huruf regional indicator; profesi biasanya berupa orang, joiner, dan sebuah benda.
Huruf beraksen dan combining character. Huruf é bisa ditulis sebagai satu code point atau sebagai e yang diikuti tanda aksen akut gabungan. Keduanya tampak identik, tetapi diurutkan berbeda, dianggap tidak sama saat dibandingkan, dan dihitung berbeda — dan kedua bentuk itu muncul di data sungguhan, sering kali di kolom yang sama.
Aksara non-Latin. Karakter Tionghoa, Jepang, dan Korea masing-masing tiga byte dalam UTF-8. Hindi, Thai, Tamil, dan Arab membentuk gugus yang dilihat pembaca sebagai satu unit, padahal terdiri dari beberapa code point.
Simbol matematika dan musik, yang berada di luar rentang dasar sehingga terhitung dua kali dalam UTF-16.
Apa yang harus dilakukan
Hitung hal yang dihitung oleh batas Anda. Penghitung yang menampilkan keempat angka langsung menjawab pertanyaannya, dan itu lebih cepat daripada menalarnya. Di dalam kode, pakai fungsi yang sesuai: Intl.Segmenter di JavaScript menghitung apa yang dilihat pembaca, len(s.encode("utf-8")) di Python menghitung byte, dan mb_strlen, bukan strlen, di PHP.
Perbaiki kolomnya, bukan formulirnya. Jika kolom database yang menjadi batasannya, solusi yang tahan lama ada di hulu: deklarasikan sebagai utf8mb4 di MySQL atau text di PostgreSQL. "utf8" versi lama di MySQL terkenal hanya memakai tiga byte per karakter dan sama sekali tidak bisa menyimpan emoji — jebakan lama yang sudah diam-diam memotong sangat banyak data sungguhan. Menghitung dengan cermat di formulir hanyalah solusi sementara untuk kolom yang seharusnya dideklarasikan dengan cara lain.
Normalisasikan sejak data masuk. Mengubah teks ke satu bentuk normal di titik masuk berarti dua cara penulisan é menjadi satu, dan perbandingan, pengurutan, serta penghitungan mulai sepakat. Setiap bahasa pemrograman punya fungsi untuk itu, dan melakukannya sekali di batas sistem jauh lebih mudah daripada menangani kedua bentuk di mana-mana.
Kasus terkait: base64
Layak disebut karena menimbulkan kejutan yang serupa. Meng-encode data sebagai base64 mengambil tiga byte sekaligus dan menuliskannya sebagai empat karakter, sehingga hasilnya sekitar sepertiga lebih besar — ini soal hitungan, bukan ketidakefisienan. Lampiran 6 MB menjadi sekitar 8 MB teks, dan karena itulah file yang jelas-jelas di bawah batas ukuran bisa ditolak setelah di-encode untuk dikirim.
Hitungan yang sama menjelaskan mengapa lampiran email terpental di batas yang tampaknya sudah terpenuhi. Jika Anda mengukur sesuatu terhadap batas, ukurlah bentuk yang sudah di-encode.
Pertanyaan yang sering diajukan
Mengapa kolom 255 karakter saya menolak teks yang lebih pendek?
Hampir pasti karena kolom itu menghitung byte, bukan karakter. Huruf beraksen memakan dua byte dalam UTF-8 dan karakter CJK tiga byte, sehingga 255 byte mungkin hanya 85 karakter Jepang. Mendeklarasikan kolom sebagai utf8mb4 atau text memperbaikinya dengan benar.
Apakah satu emoji benar-benar membuat saya membayar tiga SMS?
Bisa. Pesan yang hanya berisi karakter dari alfabet GSM mendapat 160 karakter per bagian; satu karakter di luar alfabet itu mengalihkan seluruh pesan ke encoding 70 karakter. Jadi pesan 150 karakter dengan satu emoji menjadi tiga bagian, bukan satu.
Hitungan mana yang sebaiknya dipakai untuk title tag?
Tidak satu pun yang tepat — mesin pencari memotong berdasarkan lebar piksel, bukan jumlah karakter, sehingga judul berisi huruf kapital yang lebar terpotong lebih cepat daripada judul berhuruf kecil yang sempit. Sekitar 60 karakter adalah patokan umum, dan itu panduan, bukan batas.
Mengapa dua teks yang tampak identik tidak cocok?
Biasanya karena huruf beraksen ditulis dengan dua cara berbeda — sebagai satu code point di satu teks, dan sebagai huruf dasar ditambah tanda gabungan di teks lain. Menormalisasikan keduanya ke bentuk yang sama sebelum dibandingkan membuatnya cocok, dan sebaiknya dilakukan di titik data masuk ke sistem Anda.
Apakah jumlah kata lebih stabil daripada jumlah karakter?
Untuk bahasa Inggris, umumnya ya. Tetapi tidak di semua bahasa: bahasa Tionghoa dan Jepang tidak memisahkan kata dengan spasi, begitu pula bahasa Thai, sehingga menghitung kata dalam aksara itu memerlukan segmentasi, dan alat yang berbeda memberi jawaban yang berbeda.
Juga layak dibaca
PDF terlalu besar untuk email
Tiga penyebab PDF berukuran besar, dan solusi mana yang cocok untuk file Anda.
Format gambar mana?
Satu pertanyaan menentukannya. JPG, PNG, WebP, dan AVIF dibandingkan secara jujur.
PDF hasil scan dan OCR
Kenapa hasil scan tidak berisi teks, apa yang ditambahkan OCR, dan pengaturan yang menentukan akurasinya.