文字コードについての予備知識

《 初回公開:2019/11/24 , 最終更新:2020/02/01 》

文字コードにはいろいろな規格,キーワードが出てきて

文字セットと文字エンコーディング
ASCIIとShift_JISそしてCP932
UCSとUTF, UTF-8,UTF-16,UTF-32, UCS-2,UCS-4
SBCS,DBCS,MBCS
ANSIとUnicode,マルチバイト文字とワイド文字
コードポイント,コードページ
サロゲートペア
BOM

それがごっちゃになって理解が難しい。

私が理解できると思われる範囲でそれらについてまとめてみる。

【 目次 】

文字コード 文字セット 文字エンコーディング

文字コードには文字セットと文字エンコーディングがあってそれが混同されている。

文字セット(文字集合) - 文字に番号を付けて表現する

符号化文字集合(CCS,coded character set)とか言うらしい。
コンピューターは文字をそのまま認識できないので、文字に番号を付けて区別,表現する。
例えば、「あいうえお」という文字に順番を付けて「あ」は「1」,「い」は「2」とか。

asciiコード

よく知られたasciiコードの場合は「A」が16進の「41」,「B」が「42」とか

コードポイント

単純に考えると、文字に付けられた番号の事をコードポイントというのかな。

文字エンコーディング

こちらは文字符号化方式(CES,character encoding scheme)とか言うらしい。

  • 文字エンコーディングとは : JavaA2Z

    「文字エンコーディング」は、「文字コード」とほぼ同意である。
    ただし、「文字コード」はやや曖昧な用語である。
    「文字コード」は「文字の集まり」としての意味も、「変換表」としての意味も持ち、また「文字に対する整数値そのもの」を意味することもある。
    それに対して「文字エンコーディング」は「変換表」としての意味が強く、「文字の集まり」としての意味は弱い。
    また「文字に対する整数値そのもの」という意味は持たない。

これでは「文字セット」と「文字エンコーディング」の違いが良くわからない。

なぜ、バイト列に変換する必要があるかというと、コンピュータ間やファイルアクセスをおこなう場合にストリームという言葉があって

  • ストリーム (プログラミング) - Wikipedia

    ストリーム(英: stream)とは、連続したデータを「流れるもの」として捉え、そのデータの入出力あるいは送受信を扱うことであり、またその操作のための抽象データ型を指す[1]。
    出力ストリーム (output stream) を利用してデータの書き込みを行ない、また入力ストリーム (input stream) を利用してデータの読み出しを行なう。
    ファイルの入出力を扱うもの、メモリバッファの入出力を扱うもの、ネットワーク通信を扱うものなどさまざまなものがある。

このストリームを使ってデータの入出力をおこなう場合に、データをバイト列でやりとりするように統一する事で相手が何であろうと様々な入出力機器に対して一様にデータを扱う事ができる。

コンピュータ内部でのデータ処理をおこなう場合、文字列を文字セットとして扱って、外部に対して入出力をおこなう際にこの文字セットを文字エンコーディングに変換してやりとりをする方が便利なのだと思う。
また、文字エンコーディングの方式によっては転送するデータ量を削減できるというメリットもある。
Shift_JISの場合、Shift_JISそのものがバイト列になっているので文字セットと文字エンコーディングの違いを意識する必要はないようだ。

バイトストリーム

Shift_JISとCP932とコードページ

正確では無いが、文字コードのShift_JISをコードページであらわすとCP932と理解しておけば良いのかな。

Shift_JIS

  • Shift JIS(シフトJIS)とは - IT用語辞典 e-Words

    Shift JISとは、JIS規格として標準化された日本語を含む様々な文字を収録した文字コードの一つ。
    正確には「Shift_JIS」と間にアンダーバーを挟んで表記する。MS-DOSやWindowsが標準の日本語文字コードとして採用したことから広く普及した。

コードページ

  • コードページ - Wikipedia

    コードページ(英: Code page)とは、特定の符号化文字集合を指定するための数字、またはその数字で指定された符号化文字集合、あるいはそのような方法で符号化文字集合を指定するためのシステムのことである。
    CPと表示されることもある。それぞれの符号化文字集合は「コードページ○○(○○は2桁から5桁の数字)」という形で管理される。
    ...
    コードページという用語は、システムベンダ各社が管理している符号化文字集合を指す時にしか用いられず、ISO等の公的な規格の文字集合を「コードページ○○」などと呼ぶことはない。
    IBMおよび、マイクロソフトは各自、コードページを定めて管理している。

CP932

  • Microsoftコードページ932 - Wikipedia

    Microsoft コードページ 932(以下 CP932)は、マイクロソフト及び、MS-DOSのOEMベンダがShift_JISを独自に拡張した文字コードである。
    また同時に、CP932はShift_JISのWindowsアプリケーションにおける「実装」を指す用語であるとも言える。

ユニコード(Unicode)

ユニコードの文字セットはUCS(Universal Multiple-Octet Coded Character Set)と呼ばれる。

UCS-2 -> 2バイトのユニコードの文字セット
UCS-4 -> 4バイトのユニコードの文字セット

それに対して、ユニコードの文字エンコーディングはUTF(Unicode Transfer Format)。

Unicode の文字符号化方式には,主に次のようなものがあります。

  • UTF-8: 1 文字を最小 8 ビット,最大 32 ビットで表現。
  • UTF-16: 1 文字を最小 16 ビット,最大 32 ビットで表現。
  • UTF-32: 1 文字を 32 ビットで表現。

これをみるとユニコードの文字セットは固定長であるが文字エンコーディングは固定長であったり可変長であったりする。
UTF-16には更にUTF-16LEとUTF-16BEの区別があって

BOM(ByteOrderMark)とリトルエンディアン,ビッグエンディアン

サロゲートペア

サロゲートペアとは

  • Unicode - Wikipedia

    サロゲートペア(代用対)は16ビットUnicodeの領域1024文字分を2つ使い(前半 U+D800 ? U+DBFF、後半 U+DC00 ? U+DFFF)、各々1個ずつからなるペアで1024 × 1024 = 1,048,576文字を表す。
    これはちょうど16面分であり、第1面?第16面(U+10000 ? U+10FFFF)の文字をこれで表すこととした。
    加えて第0面(基本多言語面)も使用可能なので、Unicodeには合計で 1,048,576 + 65,536 - 2,048 = 111万2,064文字分の空間が確保されたことになる。
    Unicodeの符号空間が10FFFF16まで(サロゲート領域を除いて111万2064文字)とされているのはUTF-16が表現可能な限界だからである。
    サロゲートはUnicodeの符号位置の U+10000 ? U+10FFFF の範囲を16ビットユニットのペア(2つ)で表現する集合で、最初の16ビットユニットを前半サロゲートもしくはハイサロゲート、二番目を後半サロゲートもしくはローサロゲートと称する。
    ハイサロゲートは U+D800 ? U+DBFF の範囲、ローサロゲートは U+DC00 ? U+DFFF の範囲である。
    サロゲートペアはUTF-16でのみ使われ[10]、UTF-8、UTF-32ではすべての符号位置を符号化できるためこのような特別な処理は必要ない。

  • Unicode のサロゲートペアとは何か - ひだまりソケットは壊れない
  • サロゲートペア
  • 文字コードに関する覚え書きと実験

かえってわかりにくい説明になってしまうが、

サロゲートペアは2バイトUnicodeを拡張して4バイトのユニコードの文字セットの一部を表現できるようにする。
2バイトUnicodeで使用されていないU+D800 ~ U+DFFFの部分を半分に分割して、U+D800 ~ U+DBFFを上位ワード,U+DC00 ? U+DFFF上位ワードとして4バイトUnicodeを表現する。

U+D800 ~ U+DBFF で U+D800 + ( 0x00 から 0x3ff )までの 0x400(10進数で1024)
かける
U+DC00 ~ U+DFFF で U+DC00 + ( 0x00 から 0x3ff ) までの0x400(10進数で1024)

2バイトUnicodeでは 0x0000 ~ 0xffff までの 0x10000(10進数で65536)通りの文字しか表現できないのに対して、
0x10 0000(10進数で1,048,576)通りの文字
4バイトUnicodeの 0x0001 0000 ~ 0x0010 ffffの部分の文字を追加できる事になる。

その分、2バイトUnicodeのU+D800 ~ U+DFFFの部分が使用できなくなる。

サロゲートペアは正確には0xffff+1024*1024で0x10ffffの「6文字(16進数)」されると思うのだが。

サロゲートペアを使用する場合には2バイト1文字の固定長文字の原則が崩れて、4バイト1文字の場合もありうる事になる。
サロゲートペアは1バイト文字ascii に対して 日本語を表現するために2バイト文字を追加したShift_JISをイメージさせてしまう。

サロゲートペアをプログラムで処理するには

サロゲートペアの文字コードからバイナリデータへの変換規則は、
サロゲートペアの意味が理解できていれば自明の事だが。

  1. 文字コードから0x10000を引いて1番左の桁を"2"から"1"にする。これをXとする。
  2. Xを0x400で割ってその商を0xD800に足す。これを「上位サロゲート」とする。
  3. Xを0x400で割ってその剰余を0xDC00に足す。これを「下位サロゲート」とする。
  4. 上位サロゲート、下位サロゲートの順番で出力する。

サロゲートペアをプログラムで処理するには

文字セットのバイト数に関する分類

シングルバイト文字セット(Single Byte Character Sets : SBCS)

ダブルバイト文字セット(Double Byte Character Sest : DBCS)

2バイトで表現される文字。

マルチバイト文字セット(Multi-Byte Charcter Sets : MBCS)

マルチバイト文字(マルチバイトもじ)とは、

  • 1文字を複数バイトで表す体系
  • 1文字のバイト数が可変であるような体系
  • そのような体系で表される文字

を指すが、文脈により意味合いが異なる。
...
ISO 2022の体系を前提とした図形文字集合において、1文字が1バイトの文字集合(英: single-byte character set、94文字集合または96文字集合)に対して、1文字が2バイト以上の文字集合を、マルチバイト文字集合(英: multibyte character set)という。

ワイド文字セット(Wide Character Sets)

  • ワイド文字 - Wikipedia
  • マルチバイト文字 - Wikipedia

    C言語の規格において、char型以上のサイズを持つwchar_t型を利用したワイド文字(列)に対して、char型を利用して1文字あたり1バイト以上の可変長のバイト列として表したものをマルチバイト文字(列)という。
    ワイド文字に対する用語のため、1文字をもっぱら1バイトで表すシングルバイト文字であっても、この意味ではマルチバイト文字に含まれる。
    ワイド文字を内部処理に用いるプラットフォームもある。ワイド文字のサイズが2バイトあるいは4バイトの場合、本来1文字ごとに1バイトで収まるはずのASCII範囲の文字にも2バイトあるいは4バイトを費やすことになり、少なくともASCII範囲に関してはメモリ効率は劣ることになるが、処理対象のデータ中にマルチバイト文字で表現すると2バイト以上を費やすような文字が多数出現する場合は、ワイド文字を利用したほうが処理効率もメモリ効率も高くなることがある。
    ワイド文字およびマルチバイト文字の具体的な表現は環境依存であり規格には定めがない。
    これらは、実在する具体的な文字集合や符号化方式を分類する用語ではなく、固定長か可変長かという概念を定義した用語である。
    ...
    Microsoft Windowsでは、ワイド文字が2バイト(16ビット)として定義されており、符号化方式にUTF-16を利用する。

C,C++にはwchar_tというワイド文字型というのが存在する。
マルチバイト文字が可変長なのに対して、
ワイド文字は固定長の文字で、環境により文字のサイズが2バイトと4バイトの場合がある。
Windows(Microsoftの開発言語)では2バイトであるのに対して、GNU C Library (glibc)では4バイトとなっているようである。

その他の文字コードに関する参考サイト

VC++プログラミングにおけるワイド文字に対するマルチバイト文字の位置づけ

一応、マルチバイト文字は可変長の複数バイトの文字列となっているのだが、
VC++等ではユニコード文字列を処理するのにワイド文字を示すwchar_t型が、ユニコード以前のShift_JISやascii文字をマルチバイト文字と呼びこれを処理するのに従来からあるchar型が使われる。
ワイド文字は2バイト(または4バイト)の固定長でユニコードを、それに対してマルチバイト文字はワイド文字以外のシングルバイト文字とダブルバイト文字もマルチバイト文字に含まれるという位置付けになっている。

※紛らわしいのは、Windowsでのダブルバイト文字というのはShift-JISにおける2バイト文字の事を指しているような。

  • Unicode と MBCS | Microsoft Docs

    マルチバイト文字セットは、2 バイト文字セット (DBCS: Double Byte Character Set) とも呼ばれています。
    DBCS 文字は、1 バイトまたは 2 バイトで構成されます。

VC++の文字コードの扱いについては


文字コードの扱いはごちゃごちゃしていて、
何だか更に混乱させる結果になってしまったのかも知れない。

ページのトップへ戻る