読者です 読者をやめる 読者になる 読者になる

Flat Leon Works

アプリやゲームを作ってます。

扱う文字コードに迷ったらUTF-8を選ぼう

プログラム全般 技術

文字コードを決める場面

プログラミングにおいて文字コードを考えるときは、APIやファイルフォーマットなどですでに決められた文字コードに自分が合わせる場合がほとんどだと思います。しかし、自分で文字コードを決める場面というのも少なからず存在します。例えば、自作ツールのファイルフォーマットや、自作ライブラリなどでの文字列の内部表現を決める場合などです。英数字のみの場合はASCIIでいいのかもしれません。問題は日本語も扱えるようにする場合です。文字コードは何を選ぶべきでしょうか。日本語といえばやっぱりShiftJIS?内部表現としてよく見かけるUTF-16?この記事で伝えたいのはUTF-8を使いましょうということです。

文字コードに関する整理

UTF8の話をする前に文字コードについて整理したいと思います。まず文字コードとは、文字をバイト表現するための方式のことです。文字コードは「文字集合」と「符号化方式」の2つで成り立っています。「文字集合」とは、その文字コードがどの文字を扱うのかということです。例えば文字コードASCIIの文字集合は基本的に英数字のみで、「あ」のような日本語が含まれません。「符号化方式」は文字集合での位置をバイト列で表すための方式のことです。簡単にいうとデータの圧縮方式みたいなものです。文字集合での位置は「符号点」「符号位置」「コードポイント」とも呼ばれます。

ShiftJIS、EUC-JPはもう古い

ShiftJIS、EUC-JPは捨てましょう。世の中Unicodeです。

Unicodeとは何か

Unicode文字コードの1つ…というか、文字コードの集まりという感じです。Unicodeに含まれる文字コードUTF-8UTF-16UTF-32などがあります。これらが扱う文字集合はすべて同じで、違うのは符号化方式です。なのでこれらの文字コード文字集合Unicodeと呼ぶ場合もあります。Unicodeがすごいのは扱う文字集合が世界中のすべての文字だということです(実際に世界中の文字が収録されているわけではないと思いますが)。そしてUnicodeは現在ではいろいろな場面で使われ、文字コードデファクトスタンダードになりつつあります。

Unicodeの文字数 == 符号位置の数 ではない

Unicodeには文字の結合や異体字セレクタという機能があります。これら自体は文字ではありませんが、符号位置として現れ、直前の文字に作用します。そのためUnicodeでは符号位置の数 == 文字数として扱うことができないようになっています。つまり、Unicodeで文字数を得るには、1文字(符号位置)ずつ調べていく必要があるのです。これはUTF-8UTF-16UTF-32のそれぞれのメリットを考える上で重要なことです。

UTF-8UTF-16UTF-32の違い

Unicodeを使うとして、符号化方式はどれがいいのでしょうか。まずそれぞれの方式の違いを見てみましょう。

UTF-8

UTF-8は、1〜6バイトの可変個のバイト数で1つの符号位置を表します。何バイト使うのかは、先頭1バイトの上位ビットで1が何回連続するのかで決まります。この仕様により、UTF-8はASCIIとの互換性を実現しています。ASCIIで表されたテキストはそのままでUTF-8として解釈をすることが可能になっています。これはUTF-8の大きなメリットです。またUTF-16UTF-32のようにエンディアンの問題も存在しません。

UTF-16

UTF-16は16bitつまり2バイトもしくは4バイトで符号位置を表す方式です。本当は2バイトできっちり文字集合の符号位置を表す予定だったのですが、想定外の文字集合の拡大により2バイトでは足りなくなり、足りない分はUTF-16文字をもう1つ使って表すことになりました(サロゲートペアと呼ぶ)。なのでUTF-16のデータサイズから文字数を得ることはできません。そもそも前述のとおり、結合文字の問題があるので結局は1文字づつ調べる必要があるのですが。UTF-16のメリットとしては、日本語を多く扱う場合、UTF-8よりバイト数が少なくなるということがあります。

UTF-32

UTF-32は32ビットつまり4バイトで文字集合の符号位置を表します。4バイト固定で1つの符号位置を表すためわかりやすいのですが、先ほど言ったようにUnicodeには結合文字などがあるので、UTF-32のデータサイズから文字数を得ることができません。4バイト固定なのでデータサイズも大きくなります。

UTF-8を使うべき理由

UTF-8UTF-16UTF-32の違いを見てきました。あらためてなぜUTF-8を使うべきなのか説明したいと思います。まず重要なのは、結局どの方式も文字数を得るのに1文字ずつ調べる必要があるということです。固定のバイト数のUTF-32も結合文字などの事情から1文字ずつ調べる必要があります。そこはどの方式も同じように面倒だということです。その上でUTF-8にはASCIIと互換性があるという大きなメリットがあります。世の中Unicodeとは言っても英語圏ではASCIIはまだまだ使われています。そのASCIIと互換性があるというのはとても大きなメリットです。またUTF-8にはエンディアンの問題もありません。これがUTF-8を使うべき理由です。

まとめ

特に理由がない場合はUTF-8を使っておきましょう。