UnicodeとUTF-8ってどういう関係があるんだっけ…夏。
最近暑い日が続きますね。皆さんいかがお過ごしでしょうか。
今日は、毎回ググるけど分かった気になって終わってしまう、文字コード関連です。
その中でも、UnicodeとUTF-8の関係について記載していこうと思います。
まずは文字コードについて軽く説明をして、そしてUnicodeについてを解説します。
今回は、この本の内容から一部抽出してまとめています。
文字コードとは?
文字集合
文字コードの前に、まずは文字集合です。
文字集合は、文字を重複なく集めた集合のこと。
例えば、以下はひらがなの文字集合です。
これ以外にも、常用漢字の文字集合やアルファベットの文字集合など、色々な文字集合があります。
文字コード
では、文字コードとは何か。
文字コードは、文字集合の各文字に対するビット組み合わせを一意に定めたものです。
(符号化文字集合とも言います)
例えば、上で示したひらがなの文字集合に対してビット組み合わせを定めた、My文字コードが以下です。
これがPCに実装されていたとしたら、
ビット組み合わせで「000101」「000110」「000111」と入力されたら、「おかき」という文字列が生成されます。
ASCII
その文字コードの中でも、最も基本的なものはASCII(American Standard Code for Information Interchange)です。
ASCIIは7ビットの1バイト文字コードです。つまり、2^7で128個の文字が定められます。
ただ、このすべてに文字が割り当てられているわけではないです。
ASCIIの文字コードは以下です。
英数字の大文字小文字といくつかの記号が割り当てられていますね。
https://www.pahoo.org/e-soul/webtech/encode/encode02-01.shtm
UnicodeとUTF-8/16/32の関係は?
Unicode
さてここまでで文字コードについてが分かりました。
「じゃあUnicodeってのは文字コードなんだね?!その亜種がUTF-8なのかな?!」
と思うかもしれませんが、落ち着きましょう。
Unicodeは、厳密には文字コード(符号化文字集合)ではありません。
wikipediaには、以下のような記載があります。
Unicode(ユニコード)は、符号化文字集合や文字符号化方式などを定めた、文字コードの業界規格。文字集合(文字セット)が単一の大規模文字セットであること(「Uni」という名はそれに由来する)などが特徴である。
つまりどういうことだってばよ?と思っていると思います。
私なりの解釈ですが、つまりUnicodeとは、
世界のあらゆる文字を集めた文字集合に対して、それぞれ番号を割り当てた集合
です。ビット組み合わせではなく独自の番号を割り当てているので、文字コードではないのです。
また、Unicodeはめちゃくちゃたくさんの文字を扱っています。先ほどのひらがなであれば2次元の表で表せましたが、Unicodeはなんと4次元で文字と番号を表します。
その4次元とは、群/面/区/点です。4つを指定すると、文字が一意に決まるわけです。
その4つを指定するとき、Unicodeの番号だよということでU+を頭につけて指定します。
例えば、U+306Cは「ぬ」を表します。
UTF-X
Xには8,16,32が入りますが、これは何なのか。
全て、Unicodeで表した番号をビット組み合わせに変換する方式のことを言います。
その変換する方式の違いで、8,16,32が分かれています。
例えば、先ほどの「ぬ」はUnicodeではU+306Cでした。
それが、UTFシリーズでは以下のようなビット組み合わせに変換されます。(16進数で記載)
UTF-8:E3 81 AC(3バイト)
UTF-16:30 6C(2バイト)
UTF-32:00 00 30 6C(4バイト)
さて、それぞれを軽く説明していきます。
先に言っておくと、UTF-32が一番楽に計算できます。次点がUTF-16。一番複雑なのがUTF-8です。(個人の感想)
UTF-32
UTF-32は4バイト固定です。一番容量を食います。
さて、UTF-32は簡単です。Unicodeの番号をそのままビット組み合わせにしたものが、UTF-32です。
Unicodeは群/面/区/点の4次元で文字を指定していると言いました。つまり、4バイトあれば文字を指定できます。
UTF-32は、4バイト確保しているので、そのままビット組み合わせとして指定できるのですね。
「ぬ」の例でも、U+306Cを「00 00 30 6C」と変換していました。そのままですね。
UTF-16
UTF-16は、基本2バイトなんですが一部4バイトになります。
「基本」と書いたのは、Unicodeの中のBMP(基本多言語面)に当たるものは2バイトで示せ、それ以外は4バイトになるからです。
はい、BMPの説明をします。
元々Unicodeは、16ビット(2バイト)の組み合わせで生まれました。つまり、2^16通りの文字が表せますね。
ですが、途中で「あかん、これだとたりーん!」となってしまったわけです。
なので、32ビット(4バイト)に拡張しました。
ただ、大体主要な文字は16ビット(2バイト)で表せていたんですね。日本語とか、英数字とか。
そのため、主要なこの16ビット(2バイト)の組み合わせを、BMPと言います。
BMPは2バイトの組み合わせで表現可能なので、群と面が00、00固定となります。
BMP以外の文字の例は、よくこの ほっけ と読む文字が出てきます。
𩸽
これは、Unicodeで言うと「U+00029E3D」になります。群は00ですが、面が02となっています。つまり、BMP外の文字ですね。
さて、UTF-16の説明に戻ります。
このBMPに入っている文字であれば、Unicodeの番号をそのままビット組み合わせに変換できます。
つまり、BMP内であればUTF-16もUTF-32も同じ(UTF-32は1,2バイト目が00 00になりますが)です。
では、BMP外の文字を表すとき…その時は、サロゲートペアという仕組みを使います。
この仕組みは、詳しく知りたい方はこの本を買うかググってください。
UTF-8
ラスボスのUTF-8です。
これは、1~4バイトで文字を表します。一番容量がお得な文字コードです。
「ぬ」の例でもありましたが、UTF-8はUnicodeの番号と同じようにあらわせません。
そのため、一番複雑です。
UTF-8:E3 81 AC(3バイト)
UTF-16:30 6C(2バイト)
UTF-32:00 00 30 6C(4バイト)
ざっくりいうと、Unicodeの番号をあるルールに則ってUTF-8のバイト列に変換できます。
それが、以下の表です。
例えば、「ぬ」をUTF-8に変換してみましょう。
Unicodeでは「U+306C」でした。306Cはこの表で言うと3行目に当たりますね。
では次に、306Cは16進数なので、それを2進数に変換すると、こうなります。
0011000001101100
さらにそれを表の右側のバイト列のxに当てはめると、こうなります。
1110xxxx 10xxxxxx 10xxxxxx
↓
11100011 10000001 10101100
さらにさらにこれを16進数したら…「ぬ」のUTF-8でのバイト表現の完成です!
E381AC
ここで確かめてみましたが、合ってそうですね。
【みんなの知識 ちょっと便利帳】URLエンコード/デコードツール = UTF-8