[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.2 gauche.charconv - 文字コード変換

Module: gauche.charconv

与えられたデータストリームの文字エンコーディングを変換するための手続き群を提供する モジュールです。

このモジュールはまた、open-input-filecall-with-output-file等のファイルストリームを作成する手続きに :encodingキーワード引数が与えられた場合に暗黙にロードされます。

リリース0.5.6より、Gaucheは日本語の主要エンコーディング (ISO2022JP, ISO2022JP-3, EUC-JP (EUC-JISX0213), Shift_JIS (Shift_JISX0213), UTF-8 (Unicode 3.2))間の変換を自前で持つようになりました。 上記以外のコードとの変換はiconv(3)を利用します。 サポートされるコーディングシステムに関する詳細は サポートされる文字エンコーディングを参照して下さい。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.2.1 サポートされる文字エンコーディング

CESの名前は文字列またはシンボルで指定します。大文字小文字の違いは無視されます。 同じCESにいくつかの別名がついていることがあります。

CES名 "none" は特殊です。Gaucheのネイティブエンコーディングがnoneの 場合、Gaucheは文字列を単なるバイト列として扱い、そのエンコーディングの解釈は アプリケーションに任されます。したがって、CES "none" への変換、および "none" からの変換は「何もしない」変換として扱われます。

特定の変換がシステムでサポートされているかどうかは次の手続きで調べることができます。

Function: ces-conversion-supported? from-ces to-ces

CES from-cesからto-cesへの変換がサポートされていれば#tを、 そうでなければ#fを返します。

システムがfrom-cesからto-cesへの変換を部分的にしか サポートしていない場合でもこの手続きは#tを返すことに注意して下さい。 そのような場合、実際の変換作業はfrom-cesにあってto-cesにない コードを置換文字に置き換える等で情報を失うかもしれません (例えば、UnicodeからEUC-JPへの変換はサポートされていますが、 UnicodeにはEUC-JPにない文字も含まれています)。

from-cesto-cesが "none" ならばこの手続きは常に#tを 返します。なぜならそのような変換は常に成功するからです(何も変換しないわけですが)。

 
;; 内部エンコーディングからEUC-JPに変換できるか?
(ces-conversion-supported? (gauche-character-encoding) "euc-jp")

また、CESを扱う二つの便利な手続きが用意されています。

Function: ces-equivalent? ces-a ces-b &optional unknown-value

CES ces-aces-bがシステムの知る限りで等価だった場合に #tを、等価でない場合に#fを返します。 システムがその等価性を判断出来ない場合はunknown-valueに与えられた 値を返します。そのデフォルトは#fです。

CES名 "none" はワイルドカードのように動作します。それはどんなCESとも 等価と見倣されます。(従って、ces-equivalent? は遷移的ではありません。 この手続きは、二つのCESを知った時に相互の変換が 必要かどうかを判断するためのものです)。

 
(ces-equivalent? 'eucjp "EUC-JP")            ⇒ #t
(ces-equivalent? 'shift_jis "EUC-JP")        ⇒ #f
(ces-equivalent? "NoSuchEncoding" 'utf-8 '?) ⇒ ?
Function: ces-upper-compatible? ces-a ces-b &optional unknown-value

CES ces-bでエンコードされた文字列が、システムの知る限りで 変換無しにces-aでエンコードされたものと見倣せる場合に#tを 返します。見倣せない場合は#fを返します。 システムが判断できない場合はunknown-valueに与えられた 値を返します。そのデフォルトは#fです。

ces-equivalent?と同様に、CES名 "none" はワイルドカードとして 働きます。ces-aces-b が "none" であれば、 常に#tが返されます。

 
(ces-upper-compatible? "eucjp" "ASCII")             ⇒ #t
(ces-upper-compatible? "eucjp" "utf-8")             ⇒ #f
(ces-upper-compatible? "utf-8" "NoSuchEncoding" '?) ⇒ ?

日本語の文字セットJIS X 0201及びJIS X 0213のエンコーディング (EUC_JP、Shift JIS、UTF-8及びISO2022-JP) 間の変換に関しては、 Gaucheが内部に変換アルゴリズムを持っています (詳細は下の注記を参照)。 それ以外のCESに関しては、リンクされていればGaucheはiconv(3)を用いて 変換を行います。

出力CESへマップ不可能な入力文字に出会った場合、Gaucheの変換ルーチンは その文字が入力CESでマルチバイトである場合はgeta mark '〓' (U+3013) に、 入力CESでシングルバイトである場合は '?' に置換します。 iconvによる変換でマップ不可能な文字に出会った場合の処理はiconvの実装に 依存します(例えばglibcではエラーとなります)。

変換ルーチンが、入力CESとして不正な入力文字列に出会った場合は エラーが報告されます。

Gaucheの内部変換アルゴリズムの詳細: EUC_JP、Shift JIS、及びISO2022JP間の変換は可能な限り計算で行います。 文字が未定義のコードポイントも計算式に従って変換されます。 Unicode(UTF-8)とEUC_JP間の変換はテーブルルックアップによって行われます。 UnicodeとShift JISまたはISO2022JP間の変換は、入力CESを一度EUC_JPに 変換し、それを出力CESに変換することによって行います。 入力と出力のCESがGaucheの内部アルゴリズムがサポートする範囲で等しかった場合、 Gaucheの変換ルーチンはエンコーディングの正当性はチェックせず、 単に入力を出力にコピーします。

EUC_JP, EUCJP, EUCJ, EUC_JISX0213

ASCII, JIS X 0201カナ、JIS X 0212、及びJIS X 0213文字セットをカバーします。 JIS X 0212は、単にJIS X 0213と重ならないコードを使っているためにサポート されていますが、他のCESへの変換は行われないので注意して下さい。 なるべくJIS X 0213の使用をおすすめします。

SHIFT_JIS, SHIFTJIS, SJIS

Shift_JISX0213をカバーします。但し、0x5cと0x7eに関しては JIS X 0201 Roman (YEN SIGNとOVERLINE) ではなく ASCII (REVERSE SOLIDUSとTILDE) にマップされます。

UTF-8, UTF8

Unicode 3.2です。JIS X 0213中の文字のいくつかはExtension B (U+20000〜) にマップされます。JIS X 0213中の他の文字のいくつかは2つのUnicode文字 (base character + combining character)にマップされます。

ISO2022JP, CSISO2022JP, ISO2022JP-1, ISO2022JP-2, ISO2022JP-3

これらのエンコーディングは、CSISO2022JPがISO2022JPのエイリアスであることを除き 異なるエスケープシーケンスを使いますが、Gaucheの中では同じルーチンで処理されます。 これらのエンコーディングのいずれかが入力CESに指定された場合、 Gaucheは全てのバリエーションのエスケープシーケンスを認識します。 但し、ISO2022JP-2に定義された日本語以外の言語のエスケープシーケンスに関しては、 Gaucheはエスケープシーケンスの認識だけを行い、 文字は'?'あるいは'〓' に置換します。

出力に関してはGaucheは出来る限りISO2022JPでエンコードし、 JIS X 0212文字に出会ったらISO2022JP-1のエスケープシーケンスを、 JIS X 0213の第2面の文字に出会ったらISO2022JP-3のエスケープシーケンスを 用います。したがって、文字列がJIS X 0208の範囲だけで構成されていた場合は 出力はISO2022JP互換となります。 厳密には、JIS X 0213では包摂基準の変更により、 「JIS X 0208と同じコードポイントを用いるがJIS X 0208のエスケープシーケンスを 使ってはいけない文字」というのが定義されています。 Gaucheでは互換性のため、これらの文字もJIS X 0208のエスケープシーケンスを 用いてエンコードします (これは、Emacs-Muleにおけるiso2022jp-3-compatible モードと同じ方針です)。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.2.2 文字エンコーディングの自動判定

しばしば、入力のCESが未知であり、可能性のあるいくつかの候補から入力のCESを 推測しなければならない場合があります。推測するアルゴリズムはいくつも考えられるので、 それぞれに名前がついています(ワイルドカードCES)。 今のところ、一つのアルゴリズムしか実装されていません。

"*JP"

日本語のテキストのCESを、ISO2022-JP(-1,2,3), EUCJP, SHIFT_JIS または UTF-8の いずれかであるとして推測する。

ワイルドカードCESは、いくつかの変換関数においてCES名の代わりに使うことができます。

Function: ces-guess-from-string string scheme

文字列stringのCESを、CES推測アルゴリズムscheme ("*JP"など) を使って推測し、結果のCES名を返します。もしどのCESにも該当しないデータが 含まれていれば#fが返されます。複数のCESが可能である場合、 ネイティブエンコーディングが含まれていればそれを、 そうでなければ可能なCESからどれかひとつが選んで返されます。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.2.3 変換ポート

Function: open-input-conversion-port source from-code &keyword to-code buffer-size owner?

文字が符号化方法from-codeで符号化されているデータを読み出せる 入力ポートsourceを取り、符号化方法to-codeで符号化されたデータを 読み出せるポートを作成して返します。

to-codeが省略された場合はネイティブのCESと見なされます。

buffer-sizeは変換のための内部バッファのサイズを指定します。 省略時のサイズは1Kバイト程で、通常の使用には問題ないサイズです。

入力のCESが不明な場合、"*JP"などのCES推測アルゴリズム名をfrom-code として指定することができます。変換ポートは最高でバッファサイズまでのデータを先読みし、 CESを推測しようとします。そのアルゴリズムで推測されるどのCESにも該当しないデータが 検出された場合はエラーが報告されます。もし複数のCESが可能であるようなデータであった 場合は、Gaucheのネイティブエンコーディングが可能なCESに含まれていればそれが選ばれ、 そうでなければいずれかのCESが適当に選ばれます。従って、バッファサイズが小さすぎると 誤った判定をする可能性が高くなります。大抵のテキストドキュメントに対して、 既定のバッファサイズは十分ですが、大きなテキストのほとんどがASCII文字で最後だけ マルチバイト文字が現われるようなテキストでは誤判定の可能性があります。 最悪の場合でも結果を保証するには、テキスト全体が格納できるバッファサイズを指定すると 良いでしょう。

通常、open-input-conversion-portは変換が全て終了した後でもsource はオープンしたままにします。キーワード引数owner?に真の値を指定すると、 EOFが読まれた後でsourceはクローズされます。

例を示しましょう。以下のコードは未知のCES(但しEUC-JP, SJIS, ISO2022-JP, UTF8の いずれかであることは分かっている)で書かれたテキストファイル‘unknown.txt’を 読みだし、文字エンコーディングをEUC-JPに変換して‘eucjp.txt’に書き出します。

 
(call-with-output-file "eucjp.txt"
  (lambda (out)
    (copy-port (open-input-conversion-port
                 (open-input-file "unknown.txt")
                 "*jp"             ;guess code
                 :to-code "eucjp"
                 :owner? #t)       ;close unknown.txt afterwards
               out)))
Function: open-output-conversion-port sink to-code &keyword from-code buffer-size owner?

文字のエンコーディングをfrom-codeからto-codeに変換して 出力ポートsinkに書き出すような出力変換ポートを作成して返します。 from-codeが省略された場合はネイティブのCESと見なされます。 from-codeにもto-codeにも、CES推測アルゴリズム名を 使用することはできません。

buffer-sizeは内部で変換に使われるバッファサイズを指定します。 出力変換ポートに書き出された文字は、flushを使って明示的に フラッシュするか出力変換ポートが閉じられるまで、バッファ内に残っている可能性があります。

通常、出力変換ポートがクローズされてもsinkはクローズされません。 owner?に真の値を与えれば、出力変換ポートのクローズ時にsinkを クローズするようにできます。

Function: ces-convert string from-code &optional to-code

from-codeでエンコーディングされた文字列stringto-codeでエンコーディングされた文字列に変換します。 to-codeがネイティブエンコーディングで無い場合、返される文字列は バイト文字列(不完全な文字列)であるかもしれません。

from-codeにはCES推測アルゴリズム名("*JP"など)を与えることができます。 to-codeが省略された場合はネイティブエンコーディングと見なされます。

Function: call-with-input-conversion iport proc &keyword encoding conversion-buffer-size
Function: call-with-output-conversion oport proc &keyword encoding conversion-buffer-size

この2つの手続きを使うと、元のポートのエンコーディングとは異る一時的な エンコーディングをもつ文字I/Oを行うことが可能です。

call-with-input-conversion は、文字エンコードencoding を もつ入力ポート iport をとり、procを一つの引数、すなわち、 変換入力ポートとともに呼びだします。このポートから、proc は文字を Gauche の内部エンコーディングで読み込むことができます。いったん、 procが呼ばれたら、EOFまでのすべての文字を読み込まなくてはなりません。 後述の注意を参照してください。

call-with-output-conversion は、文字エンコーディング encoding を期待する出力ポート oport をとり、procを一つの引数、すなわち、 一時的な変換出力ポートとともに呼びだします。このポートへ、procは Gauche の内部エンコーディングをもつ文字を書き込むことができます。 proc が戻るか、エラーで抜けると、この一時的な変換出力ポートは フラッシュされて、クローズされます。call-with-output-conversion の呼出し側は、その後、元のエンコーディングのポートoportを使い 続けること可能です。

どちらの手続きも proc が返す値を返します。encoding のデフォルト値は Gauche の内部エンコーディングです。この2つの手続きは 必要がなければ、変換ポートを作成しません。もし conversion-buffer-size が与えられていれば、変換ポートがオープン されるときに、buffer-size 引数として使われます。

proc がアクティブであるあいだは、iport/oport を直接 使うべきではありません。文字のエンコーディングはステートフルなプロセスで 変換ポート(から/へ)の入出力を混在させると元にあるポートの状態がおかしく なってしまいます。

注意: call-with-input-conversion については、 proc が EOF を読むまでは、iport を再度利用することはできません。 これは、変換ポートがバッファを必要とし、proc がもどったときに iportへのバッファ付き入力をアンドゥする方法がないからです。

Function: with-input-conversion iport thunk &keyword encoding conversion-buffer-size
Function: with-output-conversion oport thunk &keyword encoding conversion-buffer-size

call-with-*-conversion と似ていますが、この2つの手続きは、 thunk を引数なしで呼びます、また、変換ポートはそれぞれ標準入力、標準 出力のポートにセットされます。 キーワード引数の意味は call-with-*-conversion と同じです。

Function: wrap-with-input-conversion port from-code &keyword to-code owner? buffer-size
Function: wrap-with-output-conversion port to-code &keyword from-code owner? buffer-size

不要な変換ポートを作らないようにする便利な手続きです。 各手続きはそれぞれopen-input-conversion-portopen-output-conversion-portのように動作します。 但し、指定されたCES間の変換が必要でないとシステムが知っている場合は、 変換ポートは作られず、portがそのまま返されます。

変換ポートが作られた場合、portは常に変換ポートに所有されます (:owner #tとなる)。ポートを閉じる場合はportではなく 常にwrap-with-*-conversionが返したポートを閉じるようにして下さい。 元のportが先に閉じられた場合、変換中の結果が書き出されない可能性があります。 (変換によっては、ポートが閉じられる時点で終了シーケンスを書き出すものがあるので、 単にポートをflushするだけでは不十分です)。

:buffer-size 引数はそのまま 変換ポート作成手続きに渡されます。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]

This document was generated by Shiro Kawai on November, 22 2009 using texi2html 1.78.