文字数カウンター
テキストを五通りに同時に数えます。見たままの文字数、コードポイント (Python の len() が返す数)、UTF-16 単位 (JavaScript の .length)、単語数、行数。
「この文字列の長さは?」に答えが一つでない理由
ささいな質問に聞こえますが、テキストの長さは何を数えるかで完全に変わります。人は目に見える文字を数えます。データベースは値が占める保存量を数えます。JavaScript はまた別のものを数えます。これらの数値が食い違うとき — 絵文字・アクセント付き文字・非ラテン文字ではしばしばそうなります — 一つの「長さ」は誤解を招きます。このツールは意味のある五つの指標を並べて表示するので、自分の状況に合ったものを選べます。
五つの指標
- 文字数 (書記素): 人が 1 文字として知覚するものです。👨👩👧 のような絵文字の家族や、結合アクセント付きの文字も 1 文字として数えます — 「目で見て」数えるのに一致するのはこの数です。
- コードポイント: Unicode スカラー値の数です。目に見える 1 文字が複数のコードポイントを結合して作られることがあるため、この数は書記素の数より大きくなりがちです。
- UTF-16 単位: JavaScript が文字列の .length プロパティで報告する値です。基本多言語面の外にある文字 (多くの絵文字) は、それぞれ 2 つの UTF-16 単位を占めます。
- 単語数: 単語らしいトークンの数で、素朴に空白で区切るのではなく、Unicode を考慮して検出します。
- 行数: 改行ごとに数えた行の数です。
絵文字とアクセントが素朴な数え方を壊す理由
現代のテキストは Unicode で作られており、多くの目に見える文字を単一の単位ではなく並びとして表します。旗の絵文字は 2 つの地域表示記号です。家族の絵文字は、目に見えない「ゼロ幅接合子」で結ばれた複数の人です。アクセント付きの é は、単一のコードポイントのこともあれば、素の e に結合アクセントが続いたものであることもあります。どれも 1 文字に見えますが、指標によっては 2 つ・3 つ、あるいはそれ以上として数えられます。手で数えたり、一つの数を信じたりするとバグにつながるのは、まさにこのためです。
どの数を使うべきか?
- 人が目にする文字数制限 (プロフィール、ツイート風の欄、SMS のプレビュー): 文字数 (書記素) を使ってください。ユーザーが数えるものに一致します。
- JavaScript の文字列処理、配列の添字操作やスライス: UTF-16 単位を使ってください。.length と文字列の添字はこれに基づいています。
- データベースの列サイズ: 列が文字単位かバイト単位かを確認してください — 多くはバイト制限で、UTF-8 のバイト数はこれらのどの数とも異なります。
- エディター向けの単語数・行数、読みやすさの指標: 単語数と行数の指標を使ってください。
Python と JavaScript がそれぞれ「長さ」と呼ぶもの
上の五つのうち二つは、多くの人がこのページに来る理由そのものであり、それぞれ別の言語のものです。Python の len() と JavaScript の .length はどちらも文字列の長さと説明されますが、素の ASCII を超えたとたん、同じテキストについて同じ瞬間に違う数を返します。どちらも間違ってはいません。数えている単位が違うだけで、両方の欄を上に並べてあるのは、その差を推測ではなく読み取れるようにするためです。
- Python: len() は Unicode コードポイントの数を返します。Python 3 の文字列がコードポイントの並びだからです。「コードポイント」の欄を見てください。それが len() の返す数です。
- JavaScript: .length は UTF-16 コード単位の数を返します。JavaScript の文字列が UTF-16 で保持されているからです。「UTF-16 単位」の欄を見てください。一方 Array.from(text).length は文字列をコードポイント単位でたどるので、Python と一致します。
- どちらも目に見えるものを数えてはいません。「文字数」の欄は書記素の数で、どちらの言語の組み込みの長さもこれを返しません。JavaScript には Intl.Segmenter が、Python には外部パッケージが要ります。人が読む上限を課すのであれば、見るべきはこの欄です。
- 「単語数」と「行数」もどちらの言語のものでもありません。空白と改行で分割すればどちらでも近い値は出せますが、どちらもここに出ている Unicode を考慮した数からずれます — 空白を書かないテキストでも、句読点でも、テキストの末尾で終わる改行でも。
例を読み込むボタンで入る例が、その差を見る最短の道です。そこにある家族の絵文字は、読み手にとっては一文字、Python にとっては五つのコードポイント、JavaScript にとっては八つの UTF-16 単位です。五つのコードポイントのうち三つが基本多言語面の外にあって二単位ずつを占め、その間の見えない接合子二つが一単位ずつを占めるからです。つまり、二十文字書ける欄は目で見て確かに二十文字入りますが、どちらの言語で書いた素朴な検査も、収まるはずのテキストを弾いてしまいます。
長さはバイト数ではない
上の五つの数はどれもバイト数ではなく、この二つは取り違えられやすいものです。数え上げはテキストそのものの性質ですが、バイト単位の大きさは、テキストを何らかのエンコーディングで書き出したあとの性質です。同じ文字列でも UTF-8 では一つの大きさになり、UTF-16 では別の大きさになります。バイトで測るものはエンコードしたあとに測るほかなく、どのエンコーディングを選んだかが答えの一部です。
- UTF-8 はほとんどのものが使っている可変長のエンコーディングです。ASCII の英字・数字・記号は一バイト、アクセント付きの文字や非ラテン文字の多くは二〜三バイト、絵文字の多くは四バイトです。百文字が百バイトになるのは、その百文字すべてが ASCII のときだけで、同じ百文字がギリシャ文字・ヘブライ文字・アラビア文字・漢字なら二〜三倍になります。
- Python: len() はコードポイントを数えるので、測る前にエンコードしてください。len(text.encode('utf-8')) が UTF-8 のバイト数で、ここに別のコーデックを書けば別の数になります。まさにそこが要点です。
- JavaScript: .length は UTF-16 単位を数えるので、これもバイト数ではありません。new TextEncoder().encode(text).length は、ブラウザでも Node でも UTF-8 のバイト数を返します。TextEncoder は UTF-8 しか出力しないので、書くべきコーデックはありません。
- 何かを数える前に、その上限がどの単位で書かれているかを確かめてください。データベースには列を文字で宣言するものとバイトで宣言するものがあり、HTTP ヘッダーの値やファイルの大きさはバイト、人が読む規則は「文字数」の欄が示すものです。文字で測るものはすでに上に出ていますが、バイトで測るものはエンコードしたあとの長さを要します。
バイト数が分かったら、その先はデータ容量変換です。生のバイト数を二つの単位系へ同時に換算し — 千の累乗にもとづくものと二の累乗にもとづくもの — 同じ大きさを手元の各ツールがどう表示するかも見せてくれます。このページはエンコードの手前で終わり、あちらはバイト数から始まります。
よくある質問
- JavaScript の文字列長に一致するのはどれですか?
- UTF-16 単位の値が JavaScript の生の .length プロパティに一致します。コードが文字列をスライスしたり添字で参照したりするなら、その挙動を左右するのはこの数です。
- 絵文字 1 つが複数文字として数えられるのはなぜですか?
- 多くの絵文字は複数の Unicode コードポイントを結合して作られています。書記素 (目に見えるもの) としては 1 文字ですが、コードポイント数と UTF-16 単位数はそれより大きくなります。だから各指標を分けて表示しています。
- 末尾の空白や改行も数えますか?
- はい。貼り付けたすべての文字を数えます。先頭・末尾の空白や改行も含みます。合計が思ったより大きい場合は、目に見えない末尾の空白がないか確認してください。
- 入力したテキストはサーバーに送られますか?
- いいえ。数え上げはすべてブラウザ内で行われます。入力または貼り付けたテキストが端末の外に出ることはありません。
- 書記素とは何ですか?
- 書記素 (「書記素クラスター」) とは、人が知覚する文字のことです。複数の下位コードポイントから作られていても、読み手が 1 文字と呼ぶ最小の単位です。
- バイト数はこれらの数とどう違いますか?
- バイト数はエンコードによって変わります。UTF-8 では、ASCII の文字は 1 バイト、多くのアクセント付き・非ラテン文字は 2〜3 バイト、多くの絵文字は 4 バイトです。ここにある五つの指標はどれもバイト数ではないため、バイト制限のある欄では先に UTF-8 に符号化してください。
関連するツール
- データ容量変換
ここに並ぶ数のどれもバイト数ではありません。バイト数はテキストを符号化して初めて決まるものだからです。その数が手元にあるなら、あちらのページはそれを 10 進系と 2 進系で並べて読み、各 OS がそれをどう呼ぶかまで示します。
- 正規表現テスター
正規表現を試す — マッチ、置換、分割。
- テキスト差分
二つのテキストを比較 — 変更された行と単語。
- Unicode 文字インスペクター
文字列がどの文字でできているかを正確に見る。