Công cụ tính chiều dài chuỗi ký tự
Khi dán một chuỗi ký tự, công cụ sẽ báo cáo độ dài của nó theo bốn cách khác nhau: .length theo chuẩn JavaScript (các đơn vị mã UTF-16), các điểm mã Unicode, các cụm ký tự (những gì người dùng nhận diện là một ký tự duy nhất), và các byte UTF-8 (những gì thực tế được lưu trong cột cơ sở dữ liệu). Những giá trị này thường không trùng khớp với nhau đối với bất kỳ chuỗi nào chứa biểu tượng cảm xúc, biểu tượng quốc gia hoặc dấu kết hợp – và sự không trùng khớp này chính là nguyên nhân gây ra nhiều lỗi.
Bốn cách hiểu về chiều dài chuỗi
-
1
Các đơn vị mã UTF-16
Giá trị mà `str.length` trả về trong JavaScript: 1 cho hầu hết các ký tự; 2 cho mọi điểm mã vượt quá U+FFFF (bao gồm biểu tượng và các chữ viết cổ).
-
2
Các điểm mã (Code Points)
Một ký tự cho mỗi giá trị scalar trong Unicode. Mỗi emoji tương ứng với một giá trị; các chuỗi ZWJ có thể chứa nhiều giá trị khác nhau.
-
3
Cụm chữ cái (grapheme cluster)
Là thứ mà người dùng gọi là “một ký tự”. `🇺🇸` gồm 2 điểm mã nhưng chỉ là 1 grapheme; tương tự, `n̈` cũng gồm 2 điểm mã nhưng chỉ là 1 grapheme.
-
4
Byte UTF-8
Thứ mà cơ sở dữ liệu của bạn lưu trữ: ASCII = 1 byte mỗi ký tự; ký tự châu Âu thông dụng = 2 byte; CJK = 3 byte; hầu hết emoji = 4 byte.
Ví dụ
| Chuỗi | JS .length | Điểm mã | Cụm chữ cái | Byte UTF-8 |
|---|---|---|---|---|
hello |
5 | 5 | 5 | 5 |
café |
4 | 4 | 4 | 5 |
😀 |
2 | 1 | 1 | 4 |
🇺🇸 |
4 | 2 | 1 | 8 |
👨👩👧 (gia đình) |
8 | 5 | 1 | 18 |
n̈ (n + dấu hai chấm trên) |
2 | 2 | 1 | 3 |
Tại sao các con số lại khác nhau
Chuỗi trong JavaScript dùng định dạng UTF-16, nên điểm mã vượt quá U+FFFF được lưu dưới dạng một cặp thay thế (surrogate pair) gồm hai đơn vị mã UTF-16. Vì vậy "😀".length === 2. Người dùng rất khó chịu với điều này vì họ coi 😀 là một ký tự duy nhất.
Grapheme còn đi xa hơn: một lá cờ quốc gia thực chất là hai điểm mã chỉ định khu vực, nhưng người dùng nhìn thấy như một lá cờ duy nhất. Trong JavaScript, "🇺🇸".length === 4, nghe có vẻ vô lý, nhưng đúng là như vậy. Để duyệt qua từng grapheme, hãy dùng Intl.Segmenter (cách hiện đại), thư viện grapheme-splitter, hoặc tự xử lý thủ công.
Byte UTF-8: thứ mà cơ sở dữ liệu của bạn lưu trữ
Đối với cột kiểu VARCHAR(255):
- Trong MySQL
utf8(thực tế là utf8mb3), 255 là số byte.caféchiếm 5 byte, nên có thể chứa 51 bản sao. - Trong MySQL
utf8mb4(UTF-8 thực sự, bao gồm emoji), vẫn tính theo byte, nhưng cách mã hóa hỗ trợ chuỗi 4 byte. - Trong Postgres
VARCHAR(255), 255 là số ký tự (điểm mã), không phải byte. - Trong SQL Server
VARCHAR, giá trị này thay đổi tùy theo collation;NVARCHARđếm theo đơn vị UCS-2 dài 2 byte.
Nếu bạn định kích thước trường cơ sở dữ liệu theo giới hạn ký tự mà người dùng nhìn thấy, hãy dùng “số byte × 4” để an toàn cho các cột UTF-8, mỗi grapheme có thể chiếm tới 4 byte cho mỗi điểm mã, và chuỗi ZWJ còn tốn thêm.
Đếm ký tự theo kiểu Twitter
Twitter đếm một tweet theo quy tắc riêng: tính theo điểm mã, nhưng emoji và chữ tượng hình CJK được tính là 2. Một tweet toàn bộ là ASCII có thể dài 280 ký tự; còn một tweet với 140 emoji thì chạm trần ở 140 “ký tự”.
Đếm ký tự SMS: 160 ký tự với GSM 7 bit. Chỉ cần một ký tự không thuộc GSM (như á, é, ñ, emoji) là mã hóa chuyển sang UCS-2, và độ dài tin nhắn giảm xuống còn 70 ký tự.
Ứng dụng thực tế
- Định kích thước cột cơ sở dữ liệu, kiểm tra số byte trước khi viết migration.
- Áp dụng hạn ngạch API, hầu hết API đếm theo byte chứ không phải ký tự.
- Kiểm tra hợp lệ biểu mẫu, hiển thị cho người dùng số ký tự chính xác khớp với kỳ vọng của họ (grapheme).
- Gỡ lỗi hiệu năng, tại sao regex này lặp chậm? Vì đầu vào dài gấp 3 lần tính theo đơn vị mã so với tính theo grapheme.
Câu hỏi thường gặp
Emoji này là một chuỗi ZWJ kết hợp nhiều điểm mã (ví dụ: emoji gia đình gồm 7 điểm mã). Twitter tính nó là 2 ký tự theo quy tắc trọng số Unicode, trong khi trình soạn thảo của bạn hiển thị 1 grapheme. Cả hai đều đúng về mặt kỹ thuật, chỉ là chúng đo những thứ khác nhau.
Trong cơ sở dữ liệu UTF-8, để an toàn hãy dành 4 byte cho mỗi ký tự dự kiến. Một trường 100 ký tự (grapheme) nên là VARCHAR(400) byte; còn nếu cơ sở dữ liệu đếm theo ký tự như Postgres thì dùng VARCHAR(100) kèm thiết lập bộ ký tự phù hợp.
Trong JavaScript: điều này phụ thuộc vào dạng chuẩn hóa. Dạng NFC tổ hợp (U+00E1) có độ dài 1; dạng NFD tách rời (U+0061 + U+0301) có độ dài 2. Cùng một ký tự hiển thị, nhưng chuỗi byte khác nhau.
Emoji gia đình và nghề nghiệp là những chuỗi ZWJ dài. Phông chữ không hỗ trợ đầy đủ sẽ kết xuất mỗi điểm mã thành một glyph riêng biệt, nên 👨💻 sẽ tách thành 👨 + 💻. Nâng cấp phông chữ của hệ điều hành sẽ khắc phục vấn đề này.
Công cụ liên quan
Trình tạo font Instagram
Tạo "font" Unicode (đậm, nghiêng, viết tay, đẳng khoảng, fraktur) để dán thẳng vào bio, tên, caption và bình luận Instagram của bạn.
Trình tạo tên thành phố
Tạo tên thành phố, thị trấn, làng và thủ đô hư cấu cho xây dựng thế giới, bản đồ, game, truyện và dữ liệu giả lập, kèm ghi chú ngắn cho từng kết quả.
Trình tìm cờ emoji
Tìm emoji cờ của 195 quốc gia theo tên địa phương, tên tiếng Anh hoặc mã hai chữ cái. Kiểm tra chuỗi Unicode và sao chép ngay trong trình duyệt.
Bộ tạo phông chữ Discord
Chuyển văn bản bình thường thành các kiểu chữ Unicode phù hợp với tên dùng trong Discord, tên máy chủ và tin nhắn, bao gồm các dạng đậm, nghiêng, fraktur, monospace và dạng trang trí.
Trình dịch chữ nổi Braille
Dịch văn bản sang chữ nổi Braille Unicode cấp 1 và giải mã Braille trở lại thành chữ cái. Xử lý chữ hoa, chữ số và dấu câu.
Trình tạo văn bản Gothic
Chuyển văn bản thường thành các ký tự Unicode kiểu blackletter (Fraktur): 𝔄 𝔅 ℭ 𝔇. Sao chép và dán vào phần tiểu sử, biểu ngữ hoặc đồ họa của ban nhạc metal.
Công cụ này có phiên bản bằng các ngôn ngữ khác
- 文字列長計算ツール [JA]
- Stränglängdsberäknare [SV]
- Stringlengteberekenaar [NL]
- مقياس طول السلسلة النصية [AR]
- 문자열 길이 계산기 [KO]
- Kalkulator Panjang String [ID]
- Calculadora de Comprimento de String [PT]
- Zeichenlängenrechner [DE]
- Calculadora de Longitud de Cadenas [ES]
- เครื่องคำนวณความยาวของสตริง [TH]
- Calculateur de longueur de chaîne [FR]
- Kalkulator długości ciągu znaków [PL]
- Калькулятор длины строки [RU]
- Dize Uzunluğu Hesaplayıcı [TR]
- 字符串长度计算器 [ZH]
- String Length Calculator [EN]
- Calcolatore della lunghezza della stringa [IT]