最終更新:
UnicodeとUTF-8の違いは?文字化け・文字数・正規化を図解
文字化けはどうして起きるの?
Unicodeは文字コードの名前?
JavaScriptのlengthと見た目が違うのは?
JavaScriptのlengthはUTF-16のコード単位の数だからだよ。😀はサロゲートペアという2つのコード単位で表すのでlengthは2。コードポイント数と、見た目のまとまりである書記素クラスタの数も別なんだ。
家族の絵文字はどう数える?
同じ見た目なのに一致しないこともある?
誤った解釈のまま保存すると、元の情報を失うことがある。まず元ファイルを残して、作成元の文字コードと読み込み設定を確認しよう。すでに置換文字の�や?になって情報が失われていれば、元データがないと戻せない場合があるよ。
□が出るのも文字化けなの?
「文字数」は何を数えるかで変わる
| 文字列 | UTF-8のバイト数 | コードポイント数 | JavaScriptのlength |
|---|---|---|---|
| A | 1 | 1 | 1 |
| あ | 3 | 1 | 1 |
| 😀 | 4 | 1 | 2 |
| 👨👩👧👦 | 25 | 7 | 11 |
JavaScriptでは次のように確認できます。
const text = '👨👩👧👦';
console.log(new TextEncoder().encode(text).length); // 25: UTF-8バイト数
console.log([...text].length); // 7: コードポイント数
console.log(text.length); // 11: UTF-16コード単位数
const segmenter = new Intl.Segmenter('ja', { granularity: 'grapheme' });
console.log([...segmenter.segment(text)].length); // 1: 書記素クラスタ数
Intl.Segmenterの対応と、実行環境が使うUnicodeの版は確認してください。書記素クラスタを数えることと、フォントで実際にどう描画されるかも厳密には別です。
正規化は文字化け修復ではない
'e\u0301'.normalize('NFC') === '\u00e9' は true になります。これは等価な文字列の表現をそろえる処理で、間違った文字コードで読み込んだバイト列を復元する処理ではありません。原文を保存したうえで、照合・検索・表示など目的に応じて変換してください。
参考資料
確認日:2026年9月27日。製品の仕様・料金・対応環境は導入時にも確認してください。
- Unicode: UTF FAQ:コードポイント、UTF-8・UTF-16、サロゲート。
- Unicode UAX #29:書記素クラスタと利用者が認識する文字の境界。
- Unicode UAX #15:NFCとNFKCの違い。
- WHATWG: Encoding:エンコード・デコードとエラー処理。