文字コードアレルギーを10分で治療する

# 概要
文字コードについてアレルギーを持っている人を10分で治療するのが本記事の目的です。

例えば下記のように考えている人はアレルギー持ちと診断できます。

- 文字コードはとりあえずUTF-8使っとけばいい
- UnicodeとUTF-8って意味はほとんど同じ
- 日本語なんて開発で使うのはバグの元

これを解決することでエンジニアなら必ず遭遇するであろう文字化けの解決が容易になり、システム連携時の落とし穴にハマりづらくなります。
また、より詳しく知りたい人は関連記事を読みやすくなります。


# 治療対象
文字コードの関連用語を挙げるとキリがないので、日本でよくでてくるものを挙げます。
後でそれぞれ解説するので、`わからない場合は飛ばしてください。`

- ASCII
- Shift JIS
- EUC-JP
- Unicode
- UTF-8
- UTF-16
- UTF-32

# 符号化文字集合と文字符号化方式
個々の文字コードの解説に先立ち、おさえておくべき用語があります。

- 符号化文字集合
- 文字符号化方式

文字コードの話をすると必ず出てくるのですが、ぱっと見よくわからない用語ですよね。
アレルギー耐性の低い人はここでノックダウンされると思います。

この用語を、色々な情報を取っ払って乱暴に図示すると以下のようになります。

![集合符号化.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321047/109403c9-e768-3aa0-9997-cc548674e8f5.png)

図だけだと何を言っているのかよくわからないですね。
この**符号化文字集合**と**文字符号化方式**について詳しく説明します。

## 符号化文字集合
こちらはどういう文字を使うのか、という集合を表します。
図左上のa(1)とかb(2)の数字は、集合内での**ID**（説明用の架空のものですが）だと思ってください。
集合はかなりの数があるのですが、日本では下記のような集合がよくでてきます。

1. 英数字+一部記号(**ASCII**)
2. 英数字+一部記号+日本語(**JIS**)
3. 世界の文字すべて(**Unicode**)

上図でいうと、左上の集合が「1. ASCII」左下の集合が「3. Unicode」といったところです。

## 文字符号化方式
こちらはさきほどの集合を、`コンピュータでどう扱うかを決める方式です。`
ここではよく、符号化なんてしないで、文字集合で出てきたIDをそのまま使えばいいじゃんという疑問が出ます。

`IDが文字集合＝符号化方式となるものも存在します。`ですが少数です。
なぜそんなややこしい手段を取るのか、その理由について説明します。

### 符号化の理由
一番の理由は`効率の良い伝達ができるからです。`

あなたは隣にいる人から、文字の純粋なIDのみを使ってメッセージを伝えられるとします。
ここで以下のようなメッセージを受け取ったらどう解釈しますか？

```
12345
```

このメッセージは1+2345なのか、12+345なのか、12+34+5なのか判断ができませんね。
これを解釈するためには、規則が必要になるというワケです。

例えば下記のような規則が送信側・受信側で共有できていれば、やり取り可能ですよね。

- すべてのIDを1バイトで表せる小さな集合だから、1バイトのID=符号とする
- すべてのIDは表すには4バイト必要な大きな集合だから、4バイトのID=符号とする

次に効率化をするためこの考えを発展させます。

例えば基本的に英語を送信するが、稀に日本語を送信するシステムがあるとします。
もし英語に割り当てる符号を小さめ(例えば1バイト)にして、日本語に割り当てる符号を大きめ(例えば3バイト)にすれば、効率よくデータ送信ができますよね。
これが符号化の主な理由です。`開発者は自分のシステムの特性にあった符号化方式を選べば良い`のです。

## 文字コードという言葉
ここまでが理解できると、ようやく文字コードという言葉について説明できます。
ぼんやりした意味で使われることが多いのですが、下記のように考えるのが正しいです。

```
文字コード=符号化文字集合+文字符号化方式
```

# よく使われる文字コード
日本でよく使われる文字コードについて以下にまとめます。

ASCII互換とは、ASCII文字については符号化方式がASCIIと全く同じことを指します。
つまり、仮にアルファベット以外は絶対に使わないシステムがあるとすれば、ASCII互換の符号化方式はShift-JIS/EUC-JP/UTF-8の何を使っても伝達される情報は同じになります。
(※1 ASCII互換の場合、ASCIIについての情報は割愛します。)

| 符号化文字集合| 文字符号化方式| ASCII互換| 符号化方法  (※1) |備考|
|:-------------|:------------|:--------:|:------------------------------|:---|
| ASCII        | ASCII       | ○        | ASCIIのID(1バイト)をそのまま利用| 日本ではほぼ使われない|
| JIS          | Shift-JIS   | ○        | 半角カナは1バイトで、それ以外は2バイト| 主にWindows環境で利用される。<br>日本語に特化しているため、`日本語の伝達効率は良い`が、他外国文字は利用不可。|
| JIS          | EUC-JP      | ○        | あまり見かけない補助漢字は3バイト、それ以外は2バイト| 主にLinux環境で利用される。<br>Shift-JISと特性が似ているが互換性はほぼない。|
| Unicode      | UTF-8       | ○        | 2バイト~4バイト| 迷ったらこれといわれるトレンド方式。ASCIIは効率よく伝達でき、ただし日本語はほとんど3バイトなので、`日本語の伝達効率は悪い。`|
| Unicode      | UTF-16      | ×        | ほとんどが2バイトだが、一部4バイトが存在|ASCIIも2バイトになるが、日本語も2バイトなので、`日本語が多い場合はUTF-8より伝送効率が良い。`|
| Unicode      | UTF-32      | ×        | 4バイト|UnicodeのIDをそのまま符号に置き換えるので単純だが、サイズが非常に大きくなるためあまり利用されていない。|

「文字コードはUTF-8でお願いします。」という言葉は間違いではないと思っていますし、きちんと伝わると思います。
ただ、`「文字符号化方式はUTF-8でお願いします。」というほうが少しドヤれます`のでこっちを使いましょう。

# 文字化け
ここまでくれば文字化けが何かは想像がつくと思います。
例えば送信側はUTF-8として記述し、受信側はUTF-16として解釈したら、うまく解釈できるはずがないですよね。

ただ`符号化方式が異なっていても解釈できるケースはあります。`
例えば送信側はShift-JIS、受信側はUTF-8だとしても、アルファベットと数字で構成されるASCII文字しか使わない場合は文字が化けません。
これは双方がASCII文字に限っては同じ符号化を行うからですね。
よくプログラミングでは、日本語なんて使うとトラブルの元とか言われますが、符号化方式について押さえておけば怖くないです。