データ通信等におけるマルチバイト文字とワイド文字の取り扱いの違いについて

はじめに

ネットワーク通信でのエンディアン変換と、文字表現ごとによるその必要性有無について同時にまとめた書籍や、WEBページがなく大変困ったので、調べられた範囲で稚拙ながらまとめてみました。

文字コードやエンコードに関する細かい話は適宜Wikipediaにリンクを張るので、そちらを参照願いたい。

マルチバイト文字とワイド文字の違い

マルチバイト文字とワイド文字のプログラミング上、あるいはデータ管理上の決定的な違いは、そのデータ型の違いです。

マルチバイト文字は漢字等の1バイトで表現できない文字をいくつかのバイトの並びとして表します。たとえばShift-JISやEUCでは漢字1文字を表すのに二つのバイトを組み合わせることで表現します。従って、マルチバイトの文字列とはバイト型(C言語でのchar型)変数の配列としてプログラム上では管理されます。

ワイド文字は漢字を含むすべての文字を1文字を数バイトの長さを持つデータ型変数として扱います。たとえばVisual C++であれば例外はありますが、1文字を2バイト超のデータ型の変数として扱います。C言語ではこのワイド文字を扱うデータ型をwchar_tとして定義しています。先ほどのVC++では2バイト長ですが、GCCでは4バイト長のデータ型として扱われます。(VC++では格納される文字のエンコードがUTF-16であり、GCCではUTF-32(UCS-4?)が直接扱われるため)

このようにマルチバイト文字はあくまでも1バイト長のデータの組み合わせでしかありませんが、ワイド文字は1文字を表すために複数のバイト長を持つ特別な型を持つことになるます。

マルチバイト文字、ワイド文字の通信上の扱い

通信上のバイトオーダーについて

バイトオーダーとはエンディアンともいい、複数のバイト長からなるデータ型のデータをどういう順序でメモリに格納していくかという、計算機のアーキテクチャで、データの上位バイトからメモリに並べる方式をビッグエンディアン (big endian)、データの下位バイトから並べる方式をリトルエンディアン (little endian) といいます。通常Intelのアーキテクチャで構築されたCPUを持つWindowsが動作するPCはリトルエンディアンです。

しかしながら、インターネットの世界ではネットワークバイトオーダーと言われるビッグエンディアンでデータをやりとりするのが習わしです。(少なくともIPやTCPのヘッダ部はビッグエンディアンでなくてはならない)

したがって、Intelのアーキテクチャ上で動作するWindows上でSocket(TCP/IP)の通信を行う場合には、データをネイティブなリトルエンディアンから、ビッグエンディアンに変換して相手に送る、送られてきたデータを先ほどとのは逆の方向で変換する必要があります。

マルチバイト文字の通信上の扱い

マルチバイト文字の文字列はEUCであれ、Shift-JISであれ、ISO-2020-JPであれ、計算機としては1バイト長のデータ型(char型)の配列でしかありません。したがって、ネットワークバイトオーダーに関係がないので、エンディアンの変換には関わりません。

ただし、実際の通信については相手との装置との間で、使用する文字コードや文字コードのエンコード方式について十分に仕様の確認をしておくことが望まれます。これが不十分だと文字化けを起こし結局通信はできても有効なデータをお互いに使用できないと言うことになります。

ワイド文字の通信上の扱い

ワイド文字は複数のバイト長からなるデータ型なので、バイトオーダーの制限に対応するためには、リトルエンディアンのアーキテクチャを持つ装置においてはエンディアンの変換が必要になります。また、ユニコードの代表的なエンコード方式であるUTF-16では1文字を16ビットつまり2バイトであるためエンコードの規格として、リトルエンディアンのUTF-16LEとビッグエンディアンのUTF-116BEが定められています。

エンディアン変換以外の注意が必要な点として、マルチバイト文字と同様に使用する文字コードや文字コードのエンコード方式について十分に仕様の確認をしておくことが望まれます。とくにUNICODEとは行っても、そもそもの文字コード表がUNICODEコンソーシアムなのか、ISOなのか、そしてそのバージョンは何であるのか、文字コードのエンコードは何を使用しているかが大変重要になります。

このようにUNICODEをUTF-16やUTF-32でエンコードし、ワイド文字として扱うのはエンディアンの制限がどこかで登場するので、通信上はあまり望ましい方法であるとは言えません。したがって、ネットワーク通信においては、UNICODEをバイト型の配列として扱うことができるUTF-8でエンコードして扱い、お互いに面倒なエンディアンの制限を避ける方法が主流になっています。

まとめ

  • ネットワーク上に流すデータは、ネットワークバイトオーダーと言って、ビッグエンディアンで並べられたデータではなくてはならないが、Intelはリトルエンディアンのアーキテクチャなので、2バイト以上のデータ長を持つデータ型のデータはエンディアンを変更する必要がある。
  • Shift-JISやEUCのようなマルチバイト文字は1バイト長データの配列でしかないので、エンディアンについては関係がない。(変換の必要がない・できない)
  • 通常はUNICODE文字が格納されるワイド文字は、UNICODEのエンコード方式によってはエンディアンの変更が必要。(例:Windows上でのエンコード形式の主流であるUTF-16ではエンディアンの変更が必要)
  • ネットワーク通信ではエンディアンの制限を逃れるためにUNICODEのエンコード方式はUTF-8を使うことが主流になっている。

 

コメントを残す