[6] 文字列をある文字コードから他の文字コードに変換することを、 一般には文字コード変換といいます。
[16] 文字コードを変更する操作 (演算) は一般に変換, convert のような語で表すことが多いようです。
[17] 関数名等としては from や to と文字コードの名称をつなげるなどして組み立てることが多く、 変換操作の動詞を含まないこともしばしばあります。
[13] バイト列を文字列データ型の値に変換することを復号、 文字列データ型の値からバイト列に変換することを符号化といいます。
[15] 現代のプログラミング言語等では内部データを Unicode文字列とすることが多いので、 Unicode への変換を復号、Unicode からの変換を符号化のように言っているかのような使われ方をされがちですが、 厳密な語法ではありません。
[4] 文字列をある文字コードから他の文字コードに変換することを、 転符号化といいます。 転符号化するソフトウェア部品を、 転符号化器といいます。>>1
[5] あまりメジャーな語ではありません。
Transcoding is the process of converting text data from one character encoding form to another. Transcoders work only at the level of character encoding and do not parse the text. Note: Transcoding may involve one-to-one, many-to-one, one-to-many or many-to-many mappings. Because some legacy mappings are glyphic, they may not only be many-to-many, but also discontinuous: thus XYZ may map to yxz. <CHARMOD>
In this definition, "many-to-one" means a sequence of characters mapped to a single character. The "many" does not mean alternative characters that map to the single character.
[2] RFC 6365 - Terminology Used in Internationalization in the IETF ( 版) http://tools.ietf.org/html/rfc6365#page-7
[3] Character Model for the World Wide Web 1.0: Fundamentals ( ( 版)) http://www.w3.org/TR/charmod/#sec-Transcoding
[173] 文字コードの変換の操作は、文字列の意味に影響を与えることがあります。
[174] UTF-8 と UTF-16 の変換のように同じ文字の定義を共有する文字コード体系同士の変換であれば、 技術的な表現方法の機械的な変換にとどまりますから、文字の意味には影響が及びません。
[175]
UTF-8 と EUC-JP の変換のように異なる符号化文字を扱う文字コード体系同士の変換だと、
変換によって文字の意味に影響が出てしまうことがあります。
例えば UTF-8 (Unicode) の鴎
と
EUC-JP (JIS X 0208) の鴎
は、
厳密には意味が異なります。変換はこの微妙な意味の違いを無視する操作となります。
[176] 変換の一方の文字コードにのみある文字が含まれる場合など、 「微妙な意味の違い」を超えた無視できない違いを生じる場合もあります。 詳しくは本記事の各項を参照。
[177] >>175 >>176 の要素を含む文字コードの変換は、破壊的な操作です。 無闇矢鱈と行うべきではありません。
[19] 文字コードの変換の操作は次のような形態のいずれかで実装されていることが多いようです。
[29] >>18 >>22 >>23 はプラットフォームの API として提供されていることもあれば、 アプリケーション等が独自に実装する場合も多いです。
[32] >>18 >>24 は独立したプログラムとなっている場合が多いです。 >>18 はこの場合テキストファイルの変換操作と言えます。
[33]
>>28 は Webページで textarea
等を使った変換ツールとして提供されているものです。
それと同等のライブラリーとして提供されている場合もあります。
8ビット符号の変換器を称していても、
実態は8ビット符号から変換された Unicode文字列同士の変換になっています。
[34] >>24 >>26 は Webブラウザーやワープロ等のソフトウェアの内部で動作するブラウザー拡張やマクロのような形になっているものです。 文字列だけでなくフォント名が変換に関与します。
[41] 入出力の文字コードは、多数に対応しているものもあれば、 特定のものに限られている実装も多いです。 ただし、 多数に対応しているものでも、古今東西の膨大な数の文字コード技術の中の限られた一部のものにしか対応できていません。
[43] 多くの実装は対象となる地域や言語に関係する文字コード群にしか対応していません。 20世紀には当該システムで採用している文字コードを中心に、 それとその他の文字コードとの変換という形態が多く見られました。 21世紀になると Unicode を中心に、 それとその他の文字コードとの変換という形態が一般化しました。
[42] 実変換処理の定義を宣言的な外部ファイルに分離するなど拡張可能な設計になっているものもありますが、 そうでない固定のものもかなり多いです。 拡張可能なものであっても、外部ファイルの記述力には限界があり、 複雑な変換は実装できません。
[46] 狭義の文字コードの変換の他に、 改行文字の変更やUnicode正規化の適用があったり、 入出力として escape や内容転送符号化や符号化語や翻字・転写の手法などを選択できたり、 それらの混在に対応していたり、 破損したデータの発見的手法による修復に対応していたりするものもあります。
[137] 文字コード体系によっては、同じ文字の表現方法に揺れ、曖昧性、その他本記事の各項に挙げるような選択肢が存在することがあり、 それらを動作オプションとして指定できるものもあります。 あるいはそうした選択まで含めた文字コードの名称・定義を提供しているものもあります。
[45] 変換不能な場合にエラーとするか、 escape 等に置き換えるか、 代替文字に置き換えるか、置換文字に置き換えるかなどを動作オプションとして指定できるものも多いです。
[44] GUI やワープロソフトウェアのマクロのような形態のものは、 動作オプションやエラーの処理などを通知したり、確認したり、選択させたりしているものもあります。
[47] 入力となる文字コードの明示的な選択を省略し、 文字コードの判定に拠るものもあります。
[48] HTML や RTF やワープロソフトウェアの独自形式のファイルなど、 単純バイト列やテキストファイルとしての変換処理ができず、 ファイル形式とフォント名に応じた処理が必要となる場合があります。
[178] JavaScript によって DOM 上に挿入された文字列のように、 HTML ファイルの静的な変換ではなく >>26 方式で実装された変換器が必須となる場合があります。
[145] 文字コードの変換の操作と関係して、文字コードの変換が可能かどうかを決定するという操作が必要となる場合がたまにあります。
charset
について「最小公倍数」を指定することを求めていました。
例えば ASCII文字のみで構成されるなら、 ISO-8859-1
よりも US-ASCII
と指定するのが良いとしていました。 ISO-2022-JP
を使い、それで表せない文字が含まれる時 UTF-8 を使う機能を有するものがあります。[149] こうした機能は実際に変換を行いながらエラーを検出する形で実装される場合もあれば、 事前に高速に判定する手法により実装される場合もあります。 どちらが好ましいかは使い方によりますが、後者の場合は実際の変換処理と乖離するリスクがあります。
[50] 一対一対応が存在する場合、入力を機械的に変換して出力するだけですから、 変換器は非常に単純になります。
[51] すべての符号が一対一対応可能な文字コード体系間の変換は、 宣言的な変換表を用意して外部化することで、容易に対応体系を増やすことができます。
[49] 平成時代初期くらいまでに欧米企業が進出していた地域の標準的な文字コードの文字のほとんどは、 Unicode と一対一対応が存在します。 また、同じ地域の同じ言語を対象とする他の文字コードとも1対1対応が存在する文字が多いです。
[52] ある文字コードで1文字として扱えるものが、他の文字コードでは複数の文字の列になることがあります。
[54] 一対一対応限定の実装より少し面倒になりますが、容易に実装できます。
[59] 西暦1990年代初頭頃に欧米企業が実装していなかった文字コードにある文字は、 それが他の Unicode文字の組合せで表現できると判断された場合 Unicode に追加されないことがほとんどなので、 それらから Unicode への変換でこのパターンとなります。
[55] ある文字コードで複数の文字の列で表されるものが、他の文字コードでは1文字となることがあります。
[56] 複数の文字のそれぞれが変換先の文字コードにも存在するなら、 1対1対応とみなして単純に変換することも可能です。
[57] 複数の文字のいずれかが変換先の文字コードに存在しないなら、 文字列を1文字に変換する必要が出てきます。
[61] 入力があってもすぐに変換先を確定できず、数文字読み続けて適切な出力文字を選ぶ必要が出てきますから、 変換処理は複雑になってきます。
[60] 1文字対多文字対応の変換の逆方向でこのパターンとなります。
[62] ある文字コードで複数の文字の列で表されるものが、 他の文字コードでは複数の文字の列で表され、 両者の構成する文字それぞれに直接的な対応関係がないことがあります。
[63] インド系文字の文字コードなどと Unicode との変換のように、 なにを符号化文字の単位とするかの考え方に大きな違いがある場合に、 この種の変換が頻出することになります。
[64] 変換処理は相当に複雑になります。
[98] ある文字コードの文字(列)から他の文字コードの文字(列)への変換が、 入力文字コードの文字(列)とその前後の文字(列)の条件という形で記述・実装されることがあります。
[99] 単純な多文字からの変換に置換できる場合も多いですが、 それでは変換表が巨大になりすぎてしまう (数千から無限大の規模となる) とき、 先読み・後読みのような手法で実装されることになります。
[100] 条件部は固定長ではない文字列になることもあります。
[101] 条件部は文字列先頭、文字列末尾、語境界、空白といった形で記述・実装されることも多いです。 こうしたものは語頭形や語末形のような文字列中の文字の位置によって変換を制御する必要がある場合に使われがちです。
[102] いずれの場合も変換処理は相当に複雑になります。
[103] 意図を正確に記述できているのか疑問が残る実装も散見されます。
[104] >>101 のように本来同等の条件を意図していたと思われるものが実装ごとに違った形で記述されていることもよくあります。 同じような条件を移植していても、プログラミング言語等で挙動が微妙に異なると思われるケースもあります。
[105] 実装の正しさの評価や他の実装との比較が困難になりますから、 可能であれば避けるべきなのでしょうが、避けることが困難と思われるケースも多いです。
[65] 入力文字コードの1つの文字に相当する出力文字コードの文字(列)に複数の候補がある場合があります。
[66] 出力の文字(列)が互いに同等なら、どれを選ぶかは実装者の任意の選択となります。 ライブラリーの類なら応用に動作オプションとして指定させる場合もあります。 プラットフォーム等で慣習が成立している場合もあります。 慣習とならず相互運用性の問題が起こることもあります。
[67] Unicode への変換で、 基底文字と結合文字の組合せを出力するか、 合成済み文字を出力するかの選択肢が存在することがあります。 一般的には合成済み文字が適切と考えられていますし、 1対1対応の変換にできるので実装も単純化できます。
[70] 出力の文字(列)が同等とはいえないなら、どれを選ぶかは文脈その他によって決めることになります。
[71] 前後の文字列との組合せで決められるなら多文字対多文字対応のような形で変換できますが、 多くの場合は機械的に選択することが困難です。
[72] 機械的に決定できなければ、不適切な場合があることを承知の上でどれかを選ぶか、 GUI による選択などの手段で個々に決めるなどの方法になります。
[73] 多くの場合はデータの劣化を恐れずどれか1つを選んで機械的に対応付ける方法を採っているようです。
[69] 実装ではなく Wikipedia の記事の対応表などでは、 複数の対応先の候補を併記する形を採っていることがあります。
[75] 入力文字コードの複数の文字に相当する出力文字コードの文字が1つとなる場合があります。 いくつかに分類できます。
[79] >>76 >>77 は実装上は大きな問題はなく、単純に変換すれば済みます。
[81] >>78 は Unicode から従来の文字コードへの変換で実装されていることがあります。 best fit などと呼ばれることがあります。 変換で失われる情報をできるだけ少なくするための配慮として実装されたものでしょうが、 情報の損失がわかりにくくなるという問題があります。
[85] インド系文字の文字コードと Unicode との変換など符号化文字の考え方が大きく異なる文字コード間の変換は、 1パスの単純な変換ではなく、複数回の変形処理の組合せとして実装されていることがよくあります。
[86] 多段変換とすることで記述や実装が単純化することも多いですが、 どんな入力がどんな出力になるかの見通しは悪いことが多いです。
[156]
機能的必然性がなく、実装の容易性のために多段化されているとみられる事例も散見されます。
例えば JavaScript で実装された変換器で、 String
の replace
メソッドを繰り返し適用することで順次文字を置換していくようなスタイルの変換器が多数あります。
[157] 一昔前なら何パスも掛けて文字列を走査するのは無駄が多く、 1パスで文字列の先頭から順に見ていくのが良いとされたのでしょうが、 現在ではパフォーマンス上の違いは微々たるもので、 実装の簡単性と視認性のメリットが遥かに上回ります。 標準メソッドだけで記述できる分、独自にループで1パスで実装するよりも高速になる可能性までありますし、 実装ミスによる不具合のリスクも減ります。
[158] ただしこの手法は入力文字集合と出力文字集合が重ならない場合には安全ですが、 そうでない場合には置換の適用順序が重要になってきます。 ところがこれをあまり意識していないと思われる事例が散見されます。 出力が再度入力条件と一致することによる置換同士の相互作用が意図的と推定できる場合もあれば、 意図的なのかどうかはっきりしない場合も多いのです。 どちらにしても変換処理全体の入出力の関係が不明瞭となりがちで、不具合の温床となっています。 開発者自身が挙動を理解しきれず冗長な置換規則や誤った置換規則を挿入したと思しき事例もあります。
[159] 多段変換の処理が実装の都合 (例えば多数の文字コード体系の相互変換のための中間符号としての利用) のために、 入出力の文字コードと無関係の文字コードを利用する場合があります。
[160] 中間符号は、入出力として現れにくいものが選ばれますが、 設計者の判断と利用者の用途が一致するとは限らず、 意図しない結果になる場合もあります。
U+3000
からの領域や U+0FFF
が使われています。U-00110000
以上の領域が使われる場合があります。
[164] ワープロのマクロとしての変換器の実装は符号位置とフォントの組を変換の入出力に使うことがあります。 同じ符号位置でもフォント名が違えば別の文字扱いになり、 変換対象にしたりしなかったりできます。 実在しないダミーのフォント名を使ったり、 実在のフォント名であっても多段変換のどの段階で変換するかを調整することで、 中間符号を用いる方式と同様の効果を実現している場合があります。
[87] 変換処理本体の単純化のために別段で正規化の処理が適用されることがあります。
[88] 入力が Unicode のとき、 NFC や NFD を適用することで、 変換処理本体が基底文字と結合文字の組合せか合成済み文字の一方だけを記述することで済ませたり、 結合文字の順序が入れ替わっている場合への対処を省略したりすることができます。
[89] 入力が翻字系の符号化のときで大文字・小文字不区別のとき、 一括してどちらかに統一してから変換処理本体を実行する場合があります。
[90] 入力の文字コードの構造上の理由から変換処理本体が基底文字と結合文字の組合せを出力したり、 合成済み文字を出力したりすることがあり、これを好ましくないと考える場合、 変換処理本体の後に NFC や NFD を適用する場合があります。
[91] こうした処理は変換処理本体の実装コストを削減できますが、 思わぬ副作用を生むこともあり、注意が必要です。
[93] インド系文字の文字コードと Unicode の変換など、 符号化文字の考え方が大きく異なる文字コードの変換では、 入出力で文字の配列順序を変更しなければならないことがよくあります。
[94] 入力または出力の数文字の部分文字列が特定のパターンに一致するかを判定し、 一致するなら順序を入れ替えるような処理を複数種類適用することになります。
[95] 部分文字列の組み合わせ数が膨大過ぎて、 多文字対多文字対応に展開するのが事実上不可能な場合が多いです。
[96] 実装によって、 出力文字コードへの変換後に正規表現の置換を組合せたり、 正規表現の置換の組合せの後に出力文字コードへ変換したり、 出力文字コードへ変換しながら順序を入れ替える状態機械を実装したり、 内部処理用の中間表現を導入したりと、 様々な実装戦略が採られています。
[97] どの方法も相当複雑になりますし、概略同じ手法でも置換パターンの作り方次第で見かけ上の処理は大きく変わってしまいます。 従ってソースコードを読んで挙動を理解するのは至難の業ですし、 諸実装の特徴を比較することも困難です。
[109] 文字コードの変換の処理で変換表の類によらない計算のみで実現できる操作はいろいろあります。 例えば、
ESC
Fe の変換[106] 平成時代初期ごろまでの日本の文字コードの変換は、 JIS X 0208 に基づくシフトJISと日本語EUCといわゆるJISコードの変換が中心で、 簡単な計算で相互に変換できました。
[107] その後 Unicode の普及期には、計算で変換できず数千行の変換表が必要となる Unicode と従来文字コードとの変換は敬遠されがちで、 Unicode 移行の障害となっていました。
[108] Unicode が一般化した現在では、計算機性能の向上もあってこうした問題が意識されることはなくなりました。 しかしシフトJISと日本語EUCといわゆるJISコードの変換も Unicode を介して行われることが増え、 Unicode との対応関係がそれぞれ微妙に異なるために従来なら無劣化で行えた変換でデータ損失が生じるような事態も生じています。
[151] 例えば出力が ISO/IEC 2022 に基づき複数の符号化文字集合を切り替えて使える符号の場合、 変換は入力文字符号から状態と文字符号の組への写像の形で記述されることになります。 出力の状態が現在の状態と同じならそのまま文字符号を出力でき、 現在の状態と異なるなら状態を切り替えてから文字符号を出力することになります。
[152] 同じ入力文字符号に対する出力の候補として、複数の状態とその文字符号がある場合があります。 この場合、現在の状態と同じものがあれば、その候補を選択すると、自然な出力となる場合が多いです。 (出力文字コードの仕様や慣習にも依存します。)
[153]
例えば Unicode から ISO/IEC 2022 に基づき JIS X 0208 と GB 2312 を使える符号へと変換する場合、
一
は JIS X 0208 と GB 2312 のどちらにも存在するので、
現在の状態に応じてどちらを使うかを決めれば、切り替えのための指示シーケンスを節約できます。
[154]
出力の状態切り替えは、 ISO/IEC 2022 のエスケープシーケンスのような文字コード層の技術による場合もあれば、
HTML の font
要素や RTF のフォント切り替えのような文書形式の機能によって行う場合もあります。
[155] エチオピア文字の文字コードやチベット文字の文字コードやギリシャ文字の文字コードなど、 変換処理が入力のフォントの違いを認識したり、出力のフォントを切り替えたりする必要のある構造のものがあります。
[118] 入力となる文字コードの文字列であるはずのものには、 適切に変換できないデータが含まれていることがあります。
[119] 具体的には
といったものが考えられます。
[123] 歴史的に文字コード関連規格は不正な入力への対処を明確に規定して来ませんでした。 こうしたものに遭遇したときの仕様上の「正しい」挙動が存在しないことが多いです。
[124] 近年の Encoding Standard はあらゆる入力に対する挙動を定めていますが、 例外的な存在です。
[125] こうしたデータに対する処理は実装によって様々です。
[133] このうち >>130 >>131 >>132 はセキュリティー上の問題を起こしかねないですし、 >>129 もライブラリー等で応用の開発者が意図していない場合には好ましからざる挙動となることがあります。 不適切なデータに対する挙動はあまり意識されないことが多いようで、 このような問題を孕んだ実装は意外と多いです。
[136] ただし出力先が HTML や RTF などでフォント指定を伴う場合のように、 >>130 が正当な選択肢となることもあります。
[179]
置換文字や escape に置き換える手法は非常によく用いられますが、
通常の入力からの変換結果との区別に注意が必要となることがあります。
例えば不正な入力を ?
に置き換えると、
本来の ?
と区別が付かなくなり、問題となる場合もあります。
[180] 多数の文字コードの出力に対応する実装や外部から動作オプションで指定できる実装は、 置換文字や escape が出力先の文字コードに存在しない文字を含む場合の対処にも注意が必要です。
[35] CodepageEncoder/data/encodings at main · NielsLeenheer/CodepageEncoder · GitHub, https://github.com/NielsLeenheer/CodepageEncoder/tree/main/data/encodings
[39] Evertype: Unicode Mapping Tables, , https://www.evertype.com/standards/mappings/
[40] sourceware.org Git - glibc.git/tree - iconvdata/, https://sourceware.org/git/?p=glibc.git;a=tree;f=iconvdata;h=494f8c50b9c9662ae85bf56184db943b0526e12c;hb=b2a8d19f4adc8ca22394b02c144b4bc867adc804
[10] xorg / font / encodings · GitLab, https://gitlab.freedesktop.org/xorg/font/encodings
[8] 当初は FTP 配布
[20] General Questions about Chararcter Mappings, , https://web.archive.org/web/19970105193228/http://stonehand.com:80/unicode/faq/mappings/general.html
[21] Questions about Mapping Tables, , https://web.archive.org/web/19970105193219/http://stonehand.com:80/unicode/faq/mappings/tables.html
.map
ファイル[170] 個別の文字コード対の変換操作については20世紀から21世紀初頭の頃に実装戦略が研究されてきているものの、 ソースコード以外にまとまった文章の形となっていない場合が大多数と思われます。
[171] 各種の文字コード技術の変換を包括的に議論したものはほとんどないと思われます。 あるとしても欧米や東アジアの主要な文字コード規格に関するものが中心で、 アジア等の各地で使われたフォント依存符号化系の変換技術や HTML, RTF の処理と組み合わさった変換技術、ワープロのマクロの形の実装手法など、 本格的な研究対象として観察されてこなかったと思われる領域が多いです。
[172] 実装技法も実装そのものも Unicode への移行の進展と共に忘れられつつあり、 技術史の観点から個々の実態調査を進めて全貌を究明し、 要素技術を整理して検証していくことが急務でしょう。
[165] 変換器は古今東西に無数に開発され利用されてきたようです。
[166] その中には十分なテストがされておらず満足に動作しないもの、 致命的な不具合があるもの、 意図した動作なのか疑わしい挙動をするものもあります。
[167] 驚くべきことに、地域コミュニティーの中心的な Web サイトの変換器であってもそのような品質のものが珍しくありません。
[168] また、同じ文字コード体系に対応していると主張する変換器同士であっても、 互いの挙動に違いがあることは珍しくありません。 どちらが正しいか判断できないもの、どちらも違った形で壊れていると思われるものも多いです。
[169] 単純な変換表の形で表現された変換器の実装や明らかに単純な変換をしている変換器の出力なら互いに比較することもできますが、 複雑なアルゴリズムで変換しているものは、ソースコードを慎重に読み込んでも互いの挙動にどのような違いがあるのか理解しづらいことがほとんどです。