Go to main content
Oracle Solaris でのアプリケーションの国際化とローカライズ

印刷ビューの終了

更新: 2016 年 11 月
 
 

コードセットの変換

システムでは、文字は一意のスカラー値として表されます。このスカラー値は、バイトまたはバイトシーケンスとして処理されます。コード化された文字セットは、文字セットに、文字とそれに対応する一意のスカラー値の間のマッピングを加えたものです。これらの一意のスカラー値はコードセットと呼ばれます。たとえば、646 (US-ASCII とも呼ばれる) は、ISO/IEC 646:1991 標準に準拠する基本ラテン文字のコードセットです。次の表は、コードセットのその他の例を示しています。

コードセット
文字
表現
US-ASCII
A
0x41
ISO 8859-2
Č
0xC8
EUC-KR
全角ラテン A
0xA3 0xC1

Unicode 標準では、もう 1 つのレイヤーが追加され、各文字がコードポイントにマッピングされます。コードポイントは 0 - 1,114,111 の範囲の数値です。この数値は、UTF-8UTF-16、または UTF-32 などの Unicode エンコード形式ごとに異なる方法で表されます。例:

コードセット
文字
コードポイント
エンコーディング
表現
Unicode
全角ラテンの大文字 A
65,313 または 0xFF21
UTF-8
0xEF 0xBC 0xA1
UTF-16LE
0x21 0xFF

注 -  コードセットはエンコーディングとも呼ばれます。コードセットエンコーディングは同じ意味で使用されますが、これらの用語間には違いがあります。

コード変換またはコードセット変換は、1 つのコードセットから別のコードセットに、バイトまたはバイトシーケンスの表現を変換することを意味します。変換に対する一般的なアプローチは、iconv() ファミリの関数を使用することです。コード変換の領域で使用される用語と iconv() 関数の一部を次に示します。

シングルバイトコードセット

文字を、0 - 255 または 0x00 - 0xFF の範囲の値セットにマッピングするコードセット。つまり、1 文字が 1 バイトで表されます。

マルチバイトコードセット

文字の一部またはすべてを複数バイトにマッピングするコードセット。

無効な文字

入力のコードセット内の無効な文字。

シフトシーケンス

マルチバイトコードセット内の特別なバイトシーケンスで、文字にはマッピングされず、デコーダの状態を変更する手段になります。

不完全な文字

入力コードセットで有効な文字を形成しないバイトのシーケンス。ただし、入力から追加のバイトが提供された場合、iconv() 関数などの変換関数への後続の呼び出しで有効な文字が形成されることがあります。これはマルチバイトストリームを変換する場合に一般的です。

同一でない文字

入力コードセットでは有効なのに、出力コードセットに同一の文字が存在しない文字。

同一でない変換

同一でない文字の変換。実装および変換オプションによっては、これらの文字は出力で省略するか、同一でない変換が発生したことを示す 1 つ以上の文字で置き換えることができます。Oracle Solaris の iconv() 関数では、デフォルトで、同一でない文字は疑問符 ('?') で置き換えられます。

iconv 関数を使用したコードセットの変換

コード変換用に libc ライブラリ内に用意されている iconv() 関数は次のとおりです。

iconv_open()

コード変換の割り当て関数

iconv()

コード変換関数

iconv_close()

コード変換の割り当て解除関数

iconvctl()

コード変換の動作を制御して問い合わせます

iconvstr()

文字列ベースのコード変換関数

iconv 関数では、コードセット間で文字または文字のシーケンスをコード変換できます。iconv_open() 関数はさまざまなコードセットをサポートしています。次のコマンドを実行して、システムで現在使用可能なサポートされているコードセットとその別名に関する情報を表示できます。

$ iconv -l

iconv モジュールは複数のパッケージに含まれているので、追加のパッケージをインストールすることで、使用可能な変換のデフォルトのリストを拡張できます。デフォルトのインストールには system/library/iconv/utf-8 パッケージが含まれ、これに、UTF-8、Unicode、その他の選択されたコードセット間で変換を行うための iconv モジュールの基本セットが含まれています。

Package Manager アプリケーションまたは pkg コマンドを使用すると、追加のパッケージをインストールできます。Package Manager を使用してインストールを行う場合、追加のパッケージは System/Internationalization カテゴリで使用できます。pkg コマンドを使用する場合、インストールには system/library/iconv/* という名前パターンを使用します。

iconv 変換モジュールは fromcode%tocode.so という形式で、iconv 関数でこれらを使用するには、/usr/lib/iconv ディレクトリの下の iconv モジュールライブラリに存在する必要があります。したがって、iconv -l コマンドによってリストされるどの 2 つのコードセット間の変換もできません。すべての iconv パッケージがインストールされており、必要なモジュールが使用できない場合は、UTF-32 などの Unicode エンコーディングを中間コードセットとして使用して、2 ステップの変換を実行できます。または、カスタム変換モジュールを開発できます。カスタムの iconv 変換モジュールを作成するには、geniconvtbl ユーティリティーを使用します。geniconvtbl ユーティリティーの入力ファイル形式の詳細は、geniconvtbl(4) のマニュアルページを参照してください。

使用例 9  iconv_open() を使用した変換記述子の作成

次のコード抜粋部分は、iconv_open() 関数を使用して、文字列 złoty (ポーランドの通貨) を 1 バイトの ISO 8859-2 コードセットから UTF-8 に変換する方法を示しています。iconv による変換を実行するには、iconv_open() 関数の呼び出しを含む変換記述子を作成し、呼び出しが正常に行われたことを検証する必要があります。

#include <iconv.h>
#include <stdio.h>
iconv_t cd;
 :
cd = iconv_open("UTF-8", "ISO8859-2");
if (cd == (iconv_t)-1) {
   (void) fprintf(stderr, "iconv_open() failed");
    return(1);
}

ターゲットのコードセットが iconv_open() 関数に対する最初の引数になります。

使用例 10  iconv() を使用した変換

次のコード抜粋部分は、iconv() 関数を使用してコードセット間の変換を行う方法を示しています。

実際の変換を行う前に、出力バッファーや、入力バッファーと出力バッファーに残っているバイト数など、iconv の呼び出しによって返される情報を保持するために、特定の変数を適用する必要があります。

ISO 8859-2 コードセットでは、L WITH STROKE 文字は 16 進数の 0xB3 で表されます。つまり、入力文字列を保持する入力バッファー (inbuf) は、表示目的で、z\xB3oty に設定されます。inbuf のコンテンツは、ストリームまたはファイルを読み取った結果になります。

#include <iconv.h>
#include <stdio.h>
#include <errno.h>

    :
int        ret;
char       *inbuf;
size_t     inbytesleft, outbytesleft;
char       outbuf[BUFSIZ];
char       *outbuf_p;

inbuf = "z\xB3oty";
inbytesleft = 5;      /* the size of the input string */

出力バッファーで変換された文字列を保持するためには、少なくとも 6 バイトが必要です。L WITH STROKE 文字は Unicode 文字の LATIN SMALL LETTER L WITH STROKE に変換されます。これは UTF-8 では 2 バイトシーケンスの 0xC5 0x82 として表されます。

ほとんどの場合、結果の文字列の実際のサイズは変換前にはわからないので、出力バッファーには十分に余裕のあるスペースを割り当てるようにしてください。この場合、stdio.h で定義されている BUFSIZ マクロは十分です。

outbytesleft = BUFSIZ;   
outbuf_p = outbuf;

この変換の呼び出しは、前述の例にある変換記述子 cd を使用します。

ret = iconv(cd, &inbuf, &inbytesleft, &outbuf_p, &outbytesleft);

iconv を呼び出したあとは、正常に呼び出されたことを確認する必要があります。呼び出しが成功し、出力バッファーにまだスペースがある場合は、文字列を Null 文字で終了させる必要があります。

  if (ret != (size_t)-1) {
          if (outbytesleft == 0) {
                  /* Cannot terminate outbuf as a character string; error return */
                  return (-1);
          }
          /* success */
          *outbuf_p = '\0';
            :
  }

呼び出しに成功すると、outbuf には UTF-8 コードセットの文字列が含まれます。これは 16 進数の \x7a\xc5\x82\x6f\x74\x79 または z\xc5\x82oty で表記されます。inbuf は、変換された文字列の末尾を指すようになります。inbytesleft は 0 になります。outbytesleft は、出力バッファーに格納されるバイト数の 6 ずつ減分されます。outbuf_p は outbuf の出力文字列の末尾を指します。

呼び出しに失敗した場合は、次のコード例に示すように、errno 値を確認してエラー事例を処理します。

  if (ret != (size_t)-1)) {
          if (errno == EILSEQ) {
                  /* Input conversion stopped due to an input byte that
                   * does not belong to the input codeset.
                   */
                    :
          } else if (errno == E2BIG) {
                  /* Input conversion stopped due to lack of space in
                   * the output buffer.
                   */
                    :
          } else if (errno == EINVAL) {
                  /* Input conversion stopped due to an incomplete
                   * character or shift sequence at the end of the
                   * input buffer.
                   */
                    :
          }
  }

最後に、変換記述子とそれに関連付けられたメモリーの割り当てを解除します。

iconv_close(cd);

Unicode コードセット間の変換のための関数

Unicode エンコード形式 UTF-8UTF-16UTF-32 のいずれか 2 つの間の変換に使用できる関数は次のとおりです。

uconv_u8tou16()

UTF-8 文字列を UTF-16 に変換します

uconv_u8tou32()

UTF-8 文字列を UTF-32 に変換します

uconv_u16tou8()

UTF-16 文字列を UTF-8 に変換します

uconv_u16tou32()

UTF-16 文字列を UTF-32 に変換します

uconv_u32tou8()

UTF-32 文字列を UTF-8 に変換します

uconv_u32tou16()

UTF-32 文字列を UTF-16 に変換します

UTF-8 文字列の処理

Unicode UTF-8 文字列の処理に使用できる関数は次のとおりです。

u8_textprep_str()

文字列ベースの UTF-8 テキスト準備

u8_strcmp()

UTF-8 文字列の比較関数

u8_validate()

UTF-8 文字を検証し、バイト長を計算します


注 -  u8_textprep_str() 関数を使用して、UTF-8 文字列を大文字または小文字に変換し、Unicode 正規化形式のいずれかを適用します。詳細は、http://unicode.org/reports/tr15/Unicode 正規化形式を参照してください。