文字コードについて整理してみた（その1）

##背景
仕事や研究などで、文字コードの話題が出た際に、主に、以下に挙げる3点について、整理・使い分けないと、話がかみ合わないことが幾度かあったため、改めて、そのポイントについて整理してみた。

##なぜ話がかみ合わないのか

ウィキペディアの「[文字集合](https://ja.wikipedia.org/wiki/%E6%96%87%E5%AD%97%E9%9B%86%E5%90%88)」内の「**符号化文字集合**と**文字符号化方式**」によれば、以下のように記載されている。

>ASCIIやISO/IEC 8859のような符号化文字集合はそれ単体で運用されることが多いが、EUC-JPやShift_JIS、UTF-8のように2つ以上の符号化文字集合を組み合わせたり変形したりして運用される文字コードがある。そこで、符号化文字集合を組み合わせて運用する方式を指して文字符号化方式という言葉が使われることがある。

また、ウィキペディアの「[**文字コード**](https://ja.wikipedia.org/wiki/%E6%96%87%E5%AD%97%E3%82%B3%E3%83%BC%E3%83%89
)」によれば、以下の記載がある。

>「符号化文字集合」や「文字符号化方式」といった用語は標準化団体によっても定義が異なるため、「これは符号化文字集合だ、いや文字符号化方式だ」といった議論は意味をなさないことがある。**元来、文字コードは文字の集合の各文字に直接一意なバイト表現を割り当てただけのシンプルなものだったが**、JIS X 0208というひとつの文字集合に対してISO-2022-JP、EUC-JP、Shift_JISなど複数の符号化方式が存在するようになってきたり、逆に複数の文字集合を切り替えて使うISO-2022-JPやEUC-JPといった符号化方式が用いられるようになってきたため、**「符号化文字集合」と「文字符号化方式」とを区別するようになった**と考えられる。

したがって、文字コードの話題では、（1）符号化文字集合（以降、**文字集合**とする）のことなのか、（2）文字符号化方式（以降、**エンコーディング**とする）のことなのか、（3）**両方**を指していることなのか、を使い分ける必要がありそうである。

以下、それぞれについて、整理してみた。（間違いなどご指摘があれば、大歓迎ですので、よろしくお願いいたします。）

##（1）文字集合

これらは、文字セット、キャラクターセット、character set、charset、符号化文字集合、文字集合、コードページ、文字コードなどとも記載・呼称される。

また、ウィキペディアの「[**コードページ**](https://ja.wikipedia.org/wiki/%E3%82%B3%E3%83%BC%E3%83%89%E3%83%9A%E3%83%BC%E3%82%B8)」によれば、以下の記載がされている。

>コードページ（英: Code page）とは、特定の符号化文字集合を指定するための数字、またはその数字で指定された符号化文字集合、あるいはそのような方法で符号化文字集合を指定するためのシステムのことである。CPと表示されることもある。それぞれの符号化文字集合は「コードページ○○（○○は2桁から5桁の数字）」という形で管理される。

さらに、以下のような記載もある。

>コードページという用語は、システムベンダ各社が管理している符号化文字集合を指す時にしか用いられず、ISO等の公的な規格の文字集合を「コードページ○○」などと呼ぶことはない。IBMおよび、マイクロソフトは各自、コードページを定めて管理している。マイクロソフトのコードページ群はMS-DOSやWindowsなどで利用されている。IBMのコードページはSystem iやDB2等の文字データ表現体系(CDRA: "Character Data Representation Architecture")をサポートするIBMシステムで利用されている。

主な[文字集合](https://ja.wikipedia.org/wiki/%E6%96%87%E5%AD%97%E9%9B%86%E5%90%88)には、前述した、**ASCII（ANSI X3.4）**や**ISO/IEC 8859**に加え、**[JIS漢字コード](https://ja.wikipedia.org/wiki/JIS%E6%BC%A2%E5%AD%97%E3%82%B3%E3%83%BC%E3%83%89)**（JIS X 0208、JIS X 0212、JIS X 0213、JIS X 0221（ISO/IEC 10646）など）がある。

また、Unicodeが、文字集合の文脈で使われることもあるが、ウィキペディアの「[**Unicode**](https://ja.wikipedia.org/wiki/Unicode)」によれば、以下の通り、**文字コードの業界規格**と説明されている。

>Unicode（ユニコード）は、符号化文字集合や文字符号化方式などを定めた、文字コードの業界規格である。文字集合（文字セット）が単一の大規模文字セットであること（「Uni」という名はそれに由来する）などが特徴である。
1980年代に、Starワークステーションの日本語化 (J-Star) などを行ったゼロックス社が提唱し、マイクロソフト、アップル、IBM、サン・マイクロシステムズ、ヒューレット・パッカード、ジャストシステムなどが参加するユニコードコンソーシアムにより作られた。**国際規格のISO/IEC 10646**と**Unicode規格**は**同じ文字コード表**になるように協調して策定されている[1]。


##（2）エンコーディング

これらは、文字符号化方式などととも呼ばれる。
エンコーディングにおいては、**シフトJIS**の話でかみ合わなくなることがある（実体験から）。

**シフトJIS**における意見交換において、**文字集合**としての用語、**エンコーディング**としての用語が整理されてない状況での議論・文書が多いからである（もはや、何が正しい、というかデファクトスタンダードなのかもわからない）。

前述のとおり、**JIS X 0208 の文字集合**に対して、**ISO-2022-JP**、**EUC-JP**、**Shift_JIS**などのエンコーディング（符号化方式）が存在するようになった。

そして、**シフトJIS**においては、シフトJISコード、Shit-JISコード、SJIS、MS932、Windows-31J、シフトJIS、MS漢字コード、Shift_JISなどの用語・記載が乱立している。

ウィキペディアの「[Shift_JIS](https://ja.wikipedia.org/wiki/Shift_JIS)」においても、文字集合なのか、エンコーディングなのかの前提の必要性が記載されている。

>Shift_JISを「シフトJISコード」と呼んで符号化文字集合（文字コード）の面のみを考える議論があるが、ここでは文字符号化方式の面に焦点を当てる）。

また、同ページには、そもそも、Shift_JISについては、以下のような記載がされている。

>Shift_JIS（シフトジス）は、コンピュータ上で日本語を含む文字列を表現するために用いられる文字コードの一つ。かつてはベンダーによる独自拡張を含む文字コード群を指した曖昧な名称であったが、1997年に標準化文書JIS X 0208:1997の附属書1で規定された。「Shift_JIS」はIANAにおける登録名である[1]。
マイクロソフトなどの各ベンダーが実装するShift_JISの亜種については「Microsoftコードページ932」を参照。Mac OSが実装する亜種については「MacJapanese」を参照。

また、[[Java] シフトJISの扱い](https://qiita.com/yoshi389111/items/9060c8b62df7cac31de9)、[Shift_JIS と Windows-31J (MS932) の違いを整理してみよう](https://weblabo.oscasierra.net/shift_jis-windows31j/)によれば、以下のように整理されている。

- シフトJISコードのエンコーディングには、**SJIS**、**MS932**があり、それぞれ、**扱える文字集合が異なる**こと
- SJISが、**JIS第1水準、JIS第2水準の文字集合**だけに対していること
- MS932は、さらに、**NEC特殊文字、NEC選定IBM拡張文字、ユーザ外字、IBM拡張文字** まで扱えること

ということで、指定できるエンコーディング名は、各言語、実装技術の指定方法を調べるのが間違いが少ないと思われる（とはいえ、ググれば、正解にはたどり着けるとは思うが）。

参考までに、[Java 8にて指定できるエンコーディング](https://docs.oracle.com/javase/jp/8/docs/technotes/guides/intl/encoding.doc.html)では、以下が記載されている。
#####■Shift_JIS（シフトジス）のエンコーディング名
- java.io APIとjava.lang API用の正準名におけるエンコーディング名は「**SJIS**」
- java.nio API用の正準名におけるエンコーディング名は、「**Shift_JIS**」

#####■IBM拡張版（CP932）と、NEC拡張版（CP932）を取り込んだ、最終形のShift_JIS（シフトジス）のエンコーディング名
- IANAには、「**Windows-31J**「と登録され、Java言語には、「**MS932**」と表記されるようになった
- java.io APIとjava.lang API用の正準名におけるエンコーディング名は、「**MS932**」
- java.nio API用の正準名におけるエンコーディング名は、「**windows-31j**」

なお、注意しておきたい点としては、Javaや、HTMLでの用語・パラメータにおいて、**キャラクターセット（キャラセット）**という用語が使われているが、**エンコーディング名**を指定する必要があること。

（例）

```
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">
<meta http-equiv="Content-Type" content="text/html; charset=Windows-31J">
```
また、[[Java] シフトJISの扱い](https://qiita.com/yoshi389111/items/9060c8b62df7cac31de9)によれば、

>いまさら気にしなくてもよさそうなぐらい古い話ですが、Java におけるCharset名の "Shift_JIS" は途中で意味が変わった（間違えていた）ことがあるらしい。

とのことで、そうなると、ただでさえ、以下のような有名な問題が伴うのに、より複雑な文字コード変換の障害が発生しかねない、状況だったようである。


#####■有名な問題

さらに、[同上](https://qiita.com/yoshi389111/items/9060c8b62df7cac31de9)によれば、エンコーディングの、**SJIS**と**MS932**では、**Unicodeコードポイントのマッピング**が一部異なるため（以下7文字）、エンコーディング名：**SJIS**でデコードした場合（Javaプログラム内で、SJISのファイルを読み込み、それをUnicodeに変換）、**MS932**でデコードした場合とが混在すると、変換不能の状況（**適当な値がセットされ文字化け**）になってしまう問題が生じる場合がありそうである。

なお、**Unicodeコードポイントのマッピング**が一部異なるのは、以下の７文字（コードポイント）。
（どういった文字化かは、以下の文字でググればわかるかと思います）

```
0x815c
0x8160
0x8161
0x817c
0x8191
0x8192
0x81ca
```

以上、（2）エンコーディングのまとめとしては、**シフトJIS（と呼ばれるワード群）**のやりとりが発生した場合、必ず、**エンコーディングを確認**した方が良い、というのを挙げておく。

#####■Unicodeのエンコーディング （2020/6/21 追記）

Unicodeのエンコーディングについて記載がなかったため、追記することとした。

一般的には、Unicodeは、文字集合のことを指し、そのエンコーディングに、**UTF-8**と、**UTF-16**などがある、といった説明がされることが多い。その一方で、[yanok.net](http://yanok.net/2016/03/utf-16-unicode.html)　などによれば、UTF-16は、Unicodeと呼ばれる（解釈される）こともあり（Windowsでのメモ帳など）、これも、細かい議論をしていくと、揉めたりする一因にもなっている（自身の経験を通して）。

さらに、UTF-8、UTF-32には、BOMの有無というものが存在し、とくに、UTF-8において、BOMが無いものを**UTF-8N**と呼ばれることもある。そして、[このUTF-8Nで作成されたデータをMicrosoftのエクセルで開くと、誤解釈をして文字化けを引き起こすといった問題も発生](https://qiita.com/nori555/items/576cf1cdf13d4fe23047)している。


##関連記事
- [文字コード嫌いだ](https://qiita.com/motoki1990/items/fd7473f4d1e28c6a3ed6)
- [波ダッシュ、全角チルダ問題まとめ](https://qiita.com/kasei-san/items/3ce2249f0a1c1af1cbd2)
- [Javaの文字化けについての対処方法を現役エンジニアが解説【初心者向け】](https://techacademy.jp/magazine/22154)
- [Unicode ～UTF-8、UTF-16との違い～](http://una.soragoto.net/topics/9.html)

長くなったので、「（3）**両方**を指していることなのか」 については、次回に整理したいと思います。