[6] 
[[文字列]]をある[[文字コード]]から他の[[文字コード]]に[[変換]]することを、
一般には[DFN[文字コード変換]]といいます。

* 呼称

[16] 
[[文字コード]]を変更する操作 ([[演算]]) は一般に[[変換]], [[convert]],
conversion のような語で表すことが多いようです。

[17] 
[[関数名]]等としては from や to と[[文字コード]]の名称をつなげるなどして組み立てることが多く、
変換操作の動詞を含まないこともしばしばあります。

[322] 
[[Python]] では変換器を [[codec]] と呼んでいます。この言葉は[[媒体]]の[[符号化]]の分野で符号化方式やその実装に言及するときに使いますが、
[[文字符号化]]の分野ではほぼ使わず、おそらく [[Python]] 界隈だけの独特の風習です。


[324] 
[[文字コードの変換]]とよく似た、ときに混同され、ときに併用・連結される処理に
[[escape]] / [[unescape]]
があります。



** 符号化と復号

[13] 
[[バイト列]]を[[文字列]]データ型の値に変換することを[[復号]]、
[[文字列]]データ型の値から[[バイト列]]に変換することを[[符号化]]といいます。

;;
[14] 
[[文字列]]に限らず、[[プログラミング言語]]等の処理用の内部データと保存用の外部データの変換を一般に[[符号化]]、[[復号]]のようにいいます。

;;
[323] 
[[符号化]] (encoding) は[[バイト列]]への変換の操作の意味 (動詞) でも、
[[文字符号化]]の方式や技術の意味 (名詞) でも、
[[文字コード]]規格への[[文字]]の追加の意味 (動詞) でも使います。
文脈によるので注意が必要です。

[15] 
現代の[[プログラミング言語]]等では内部データを [[Unicode文字列]]とすることが多いので、
[[Unicode]] への変換を[[復号]]、[[Unicode]] からの変換を[[符号化]]のように言っているかのような使われ方をされがちですが、
厳密な語法ではありません。

** 転符号化

[4] [[文字列]]をある[[文字コード]]から他の[[文字コード]]に[[変換]]することを、
[DFN[[RUBYB[転符号化]@en[transcode]]]]といいます。
[[転符号化]]する[[ソフトウェア部品]]を、
[DFN[[RUBYB[転符号化器]@en[transcoder]]]]といいます。[SRC[>>1]]

[5] あまりメジャーな語ではありません。


[FIG(quote)[
[FIGCAPTION[
[1] 
[CITE@en[[[RFC 3536]] - Terminology Used in Internationalization in the IETF]] ([TIME[2011-01-29 02:14:52 +09:00]] 版) <http://tools.ietf.org/html/rfc3536#page-6>
]FIGCAPTION]

>       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.
]FIG]



[2] [CITE@en[RFC 6365 - Terminology Used in Internationalization in the IETF]]
([TIME[2011-09-10 19:11:51 +09:00]] 版)
<http://tools.ietf.org/html/rfc6365#page-7>

[3] [CITE@en[Character Model for the World Wide Web 1.0: Fundamentals]]
( ([TIME[2005-02-15 14:24:00 +09:00]] 版))
<http://www.w3.org/TR/charmod/#sec-Transcoding>

* 変換の意味

[173] 
[[文字コードの変換]]の操作は、[[文字列]]の[[意味]]に影響を与えることがあります。

[174] 
[[UTF-8]] と [[UTF-16]] の変換のように同じ[[文字]]の定義を共有する[[文字コード]]体系同士の変換であれば、
技術的な表現方法の機械的な変換にとどまりますから、[[文字]]の[[意味]]には影響が及びません。

[175] 
[[UTF-8]] と [[EUC-JP]] の変換のように異なる[[符号化文字]]を扱う[[文字コード]]体系同士の変換だと、
変換によって[[文字]]の[[意味]]に影響が出てしまうことがあります。
例えば [[UTF-8]] ([[Unicode]]) の[CH[鴎]]と
[[EUC-JP]] ([[JIS X 0208]]) の[CH[鴎]]は、
厳密には[[意味]]が異なります。変換はこの微妙な意味の違いを無視する操作となります。


[176] 
変換の一方の[[文字コード]]にのみある[[文字]]が含まれる場合など、
「微妙な意味の違い」を超えた無視できない違いを生じる場合もあります。
詳しくは本記事の各項を参照。

[177] 
>>175 >>176 の要素を含む[[文字コードの変換]]は、破壊的な操作です。
無闇矢鱈と行うべきではありません。

** 異なる文字への変換

[301] 
様々な[[歴史的事情]]によって、意図的に別の[[文字]]への[[変換]]がなされることがあります。


- [302] [[DOSコードページ]]等で [[CL]]に[[図形文字]]が割り当てられていることがありますが、
[[Unicode]] で[[符号位置]]が一致する[[C0制御文字]]に一律で変換されることが多いです。
- [303] [[CL]], [[GL]] ([ [N[0x00]], [N[0x7F]] ]) は機械的に [[Unicode]] の
[ [CC[U+0000]], [CC[U+007F]] ] に対応付ける実装があります。
- [304] [[シフトJIS]]の [CC[0x5C]] は [CN[YEN SIGN]] ですが、
無視して [[Unicode]] の [CC[U+005C]] に対応付ける実装が大多数です。
[[日本]]市場では
[[Unicode]] の [CC[U+005C]] が [CN[YEN SIGN]]
の[[字形]]で表示される[[フォント]]が多く流通しています。
- [305] 
[[EUDC]], [[PUA]] や[[空き領域]]などの対応関係を意図的に無視して削除する実装があります。




* 変換のインターフェイス

[19] 
[[文字コードの変換]]の操作は次のような形態のいずれかで実装されていることが多いようです。

- [18] 
ある[[文字コード]]の[[バイト列]]から他の[[文字コード]]の[[バイト列]]への変換操作
- [22] 
ある[[文字コード]]の[[バイト列]]から内部処理用の[[文字列]]データ型の値への変換操作
- [23] 
内部処理用の[[文字列]]データ型の値からある[[文字コード]]の[[バイト列]]への変換操作
- [28] 
[[バイト列]]から [[Unicode文字列]]に変換された状態のある[[文字コード]]の[[文字列]]からある[[文字コード]]の[[文字列]]への変換操作
- [24] 
ある[[文書形式]]のある[[文字コード]]の[[文書]]からある[[文書形式]]のある[[文字コード]]の[[文書]]への変換操作
-- [25] [[HTML]], [[RTF]], [CITE[Microsoft Word]] など
- [26] 
ある[[データ構造]]の[[オブジェクト]]におけるある[[文字コード]]からある[[文字コード]]への変換操作
-- [27] [[HTML]] ([[DOM]]), [CITE[Microsoft Word]] (選択範囲), [CITE[LibreOffice]] 
(選択範囲) など

[29] 
>>18 >>22 >>23 は[[プラットフォーム]]の [[API]] として提供されていることもあれば、
[[アプリケーション]]等が独自に実装する場合も多いです。

[32] 
>>18 >>24 は独立した[[プログラム]]となっている場合が多いです。
>>18 はこの場合[[テキストファイル]]の変換操作と言えます。

[33] 
>>28 は [[Webページ]]で [CODE[textarea]] 
等を使った変換ツールとして提供されているものです。
それと同等の[[ライブラリー]]として提供されている場合もあります。
[[8ビット符号]]の変換器を称していても、
実態は[[8ビット符号]]から変換された [[Unicode文字列]]同士の変換になっています。

[34] 
>>24 >>26 は [[Webブラウザー]]や[[ワープロ]]等のソフトウェアの内部で動作する[[ブラウザー拡張]]や[[マクロ]]のような形になっているものです。
[[文字列]]だけでなく[[フォント名]]が変換に関与します。


[41] 
入出力の[[文字コード]]は、多数に対応しているものもあれば、
特定のものに限られている実装も多いです。
ただし、
多数に対応しているものでも、古今東西の膨大な数の[[文字コード]]技術の中の限られた一部のものにしか対応できていません。

[43] 
多くの実装は対象となる地域や言語に関係する[[文字コード]]群にしか対応していません。
[[20世紀]]には当該システムで採用している[[文字コード]]を中心に、
それとその他の[[文字コード]]との変換という形態が多く見られました。
[[21世紀]]になると [[Unicode]] を中心に、
それとその他の[[文字コード]]との変換という形態が一般化しました。

[42] 
実変換処理の定義を[[宣言的]]な外部ファイルに分離するなど拡張可能な設計になっているものもありますが、
そうでない固定のものもかなり多いです。
拡張可能なものであっても、外部ファイルの記述力には限界があり、
複雑な変換は実装できません。


[46] 
狭義の[[文字コード]]の変換の他に、

- [231] 入出力として [[escape]] や[[翻字]]・[[転写]]の手法などを選択できたり、
- [230] 出力として[[文字]]を表す[[画像]]を選択できたり、
- [228] それらの混在に対応していたり、
- [226] [[改行文字]]の変更や[[Unicode正規化]]などの[[文字コード]]に関連する他の処理の適用があったり、
- [227] 入出力として[[内容転送符号化]]や[[符号化語]]を選択できたり、
- [229] 破損したデータの[[発見的]]手法による[[修復][文字コードの修復]]に対応していたり、

... するものもあります。

[137] 
[[文字コード]]体系によっては、同じ[[文字]]の表現方法に揺れ、曖昧性、その他本記事の各項に挙げるような選択肢が存在することがあり、
それらを動作オプションとして指定できるものもあります。

[45] 
変換不能な場合にエラーとするか、 [[escape]] 等に置き換えるか、
[[代替文字]]に置き換えるか、[[置換文字]]に置き換えるかなどを動作オプションとして指定できるものも多いです。

[44] 
[[GUI]] や[[ワープロ]]ソフトウェアの[[マクロ]]のような形態のものは、
動作オプションやエラーの処理などを通知したり、確認したり、選択させたりしているものもあります。



[48] 
[[HTML]] や [[RTF]] や[[ワープロ]]ソフトウェアの独自形式のファイルなど、
単純[[バイト列]]や[[テキストファイル]]としての変換処理ができず、
[[ファイル形式]]と[[フォント名]]に応じた処理が必要となる場合があります。

[178] 
[[JavaScript]] によって [[DOM]] 上に挿入された[[文字列]]のように、
[[HTML]] ファイルの静的な変換ではなく 
>>26
方式で実装された変換器が必須となる場合があります。

-*-*-

[271] 
実務上は、処理を途中で停止したり、中断・再開したり、
ネットワークから追加のデータが到着するごとに続きを処理させる形態にしたり、
といった仕組みが必要になることがあります。
(>>269 も参照。)
こうした措置を[[プログラミング言語]]の組み込みの[[データ型]]や制御機構で自然に実現できる場合もあれば、
独自の設計が必要となる場合もあります。

[EG[

[275] 
入力が[[1バイト符号]]だけなら[[バイト列]]を分割して読み取って変換器の入力としても、
出力を単純につなぎ合わせるだけで済みます。

[276] 
入力に複数バイトの[[符号]]が含まれたり、状態を持つ[[文字コード]]体系だったりすると、
分割して変換した出力の連結は全体の変換結果と一致しないことが多くなります。

]EG]


[273] 
入力が[[空文字列]]や数バイトの短い[[バイト列]]であることもあれば、
数GBの長大な[[バイト列]]であることもあります。
こうした普通でない入力に対する設計や動作検証はなおざりにされがちなようで、
不具合を抱えている実装の事例も散見されます。
[[セキュリティー]]の問題となることもありますから、
注意が必要です。


;; [274] 
利用形態によっては、例えば短い文字列と決まっているから長大なバイト列で性能が低下しても許容できる、
とか一定以上のバイト数なら処理を拒絶する、といった実装戦略もあります。
しかしそうした場合であっても、[[セキュリティー]]は常に注視が必要です。




** 変換の入出力のデータ型と文字コード

[138] 
現代の多くの[[プログラミング言語]]には[[バイト列]]と[[文字列]]の区別があります。
また、 [[HTML]] や [[RTF]] やその他の[[文書形式]]の[[データ構造]]は、
[[文字列]]を構成要素としていることが多いです。

[139] 
組合せ上、[[文字コードの変換]]の処理の入出力は

- [140] [[バイト列]]から[[文字列]]へ
- [141] [[文字列]]から[[バイト列]]へ
- [142] [[バイト列]]から[[バイト列]]へ
- [144] [[文字列]]から[[文字列]]へ

... の4通りがあり得ます。

[181] 
[[言語情報]], [[bidi]], [[フォント]], 装飾, その他の付加情報の付随する構造を考慮すると、
組合せは更に増えます。


;; [182] 
なお、 [[RTF]] で[[フォント依存符号化]]の[[フォント]]が指定された[[文字列]]のように、
[[文字列]]データ型の仕様上の[[文字コード]]とその実際の[[文字コード]]は一致しないことがあります。

-*-*-

[183] 
古典的な[[文字コードの変換]]の実装や、単独の[[文字コード]]対の実装は、
単純に[[バイト列]]から[[バイト列]]への変換としていることが多いです。
複数の[[文字コード]]対に対応するときは、
単体の変換の実装を増やしていくことになります。

[184] 
多数の[[文字コードの変換]]に対応する実装は、
特定の[[文字コード]]を「中心」に、それと各種[[文字コード]]の変換を実装する形態としていることが多いです。

[185] 
現代の実装は[[プログラミング言語]]の[[文字列型]]の[[文字列]]を「中心」
とすることが多いです。現代の[[プログラミング言語]]の[[文字列型]]の[[文字列]]は、
ほとんどの場合 [[Unicode文字列]]です。従って [[Unicode]] からの変換、
[[Unicode]] への変換ということになります。

[186] 
古くからの実装は、 [[Unicode]] ではない[[内部符号]]を使っていることがあります。
新しい実装であっても多くの[[文字コード]]に対応する実装は独自の[[内部符号]]を採用していることがあります。

[193] 
完全独自の[[内部符号]]ではなく、 [[PUA]] を使ったり、
[[文字]]に付随する[[文字]]とは別の情報を組合せたりすることもあります。

[159] 
実装の都合 
(例えば多数の[[文字コード]]体系の相互変換のための中間符号としての利用)
のために、
入出力の[[文字コード]]と無関係の[[文字コード]]を利用する場合があります。

[160] 
中間符号は、入出力として現れにくいものが選ばれますが、
設計者の判断と利用者の用途が一致するとは限らず、
意図しない結果になる場合もあります。


- [161] [CITE[Padma]] の内部符号 [[Padma]] は [[PUA]] を使っています。
- [162] [[ビルマ文字の文字コード]]の変換器の系譜の1つでは
[CC[U+3000]] からの領域や [CC[U+0FFF]] が使われています。
- [163] [[Unicode符号位置]]ではない [CC[U-00110000]] [[以上]]の領域が使われる場合があります。
[SEE[ [[Unicodeの符号空間]] ]]


[164] 
[[ワープロ]]の[[マクロ]]としての変換器の実装は[[符号位置]]と[[フォント]]の組を変換の入出力に使うことがあります。
同じ[[符号位置]]でも[[フォント名]]が違えば別の[[文字]]扱いになり、
変換対象にしたりしなかったりできます。
実在しないダミーの[[フォント名]]を使ったり、
実在の[[フォント名]]であっても多段変換のどの段階で変換するかを調整することで、
中間符号を用いる方式と同様の効果を実現している場合があります。


[187] 
[[内部符号]]等が扱う [[Unicode]] だけでない情報の例
[SEE[ [[文字のようなもの]] ]]



-*-*-


[188] 
現代のほぼすべてのデータ (過去からデータ形式の変換により引き継がれたものを含みます。) 
は[[8ビットバイト]]で記述されています。

[189] 
[[7ビット符号]]は多いですが、実際の処理では[[8ビットバイト]]の列として扱うことになります。

[190] 
歴史的には6ビットや9ビットなど異なる単位もありますし、
[[バイト]]より大きな単位が実処理の最低単位となることもありますし、
[[プロトコル]]や[[データ形式]]が8ビット以外の単位で区切っていることも多々ありますが、
現代の計算機上の[[文字コード]]の処理の入出力となる段階では8ビット単位となっており、
変換の処理がそれ以外を想定することはまずありません。

[191] 
理屈の上では16ビット符号や32ビット符号など、より大きな単位を束ねた符号体系もいくつもありますが、
それらも結局のところは[[符号空間]]の大きさに過ぎないのであって、
それが最低の処理単位となる[[プラットフォーム]]は極めて稀です。
よって、壊れたデータが端数のバイトを持つ場合や、
[[ネットワーク]]転送時のパケット境界が[[文字]]の途中で出現する場合などを[[文字コードの変換の処理]]は考慮する必要があります。

[192] 
[[Base64]] や [CODE[application/octet-stream]]
のように端数の[[ビット]]を扱える (扱えてしまう) (こともある) [[データ形式]]もありますが、
それを[[文字コードの変換]]の実装と組合せて利用できる実装はほとんどありません。

-*-*-

[194] 
[[C言語]]など [CN[NULL]] を[[文字列]]の[[終端]]とする[[プラットフォーム]]もありますが、
そうした[[プラットフォーム]]の[[文字コードの変換]]の実装であっても、
入出力の[[バイト列]]の途中で [N[0x00]] が出現する[[文字コード]]体系や、
入出力の[[文字列]]が [CN[NULL]] を含む場合を適切に処理できる必要があります。

[EG[

[195] 
[[UTF-16]] で [[ASCII文字]]を使うと [N[0x00]] [[バイト]]が出現します。

]EG]

-*-*-


[197] 
[[文字コードの変換]]は、「どの[[文字コード]]で記述されていたか」が暗示的に保持していた情報を失うことがあります。
例えば [[GB 2312]] から [[Unicode]] へと変換すると、
それが[[中文]]で[[中華人民共和国]]で作られた可能性が高い、
という情報を失ってしまうことになります。

[198] 
[[Unicode]] は[[言語情報]]がないと[[文字のレンダリング]]を適切に行えませんが、
国ごと、言語ごとに異なる[[文字コード]]を使っていた時代のデータには明示的な[[言語情報]]が付与されていないことが多いです。
[[Unicode]] に変換して[[文字]]の表示その他の処理を行う実装は、
[[文字コード]]の情報を[[言語情報]]を補助するヒントとして活用するべきです。
[SEE[ [[文字コード等に依存した特殊な表示処理]], [[フォントの選択]] ]]

[199] 
[[ISO-2022-INT]] や [[junet]] や [[TRONコード]]のような多言語、複数地域の[[文字コード]]を組合せた形の多言語[[文字コード]]から
[[Unicode]] 等に変換するときは、[[文字]](列片)単位の[[言語]]補助情報を保持した形で変換できるような配慮が必要です。

;; [200] それに対応可能な[[内部符号]]を使うのが扱いやすいのでしょうが、
技術的に難しければ[[Unicode言語タグ]]を挿入して後からそれを解釈する形でもいいかもしれません。


** 文字コードの指定

[232] 
入出力の[[文字コード]]の指定は、
[[文字コードの識別子]]を明示的に与えるものもあれば、
関数名等に組み込まれているものもあります。

[233] 
入出力の各種の動作オプションまで含めた[[文字コード]]の名称・定義を提供しているものもあります。

[47] 
入力となる[[文字コード]]の明示的な選択を省略し、
[[文字コードの判定]]に拠るものもあります。

;; [270] 
その場合、[[応用]]に判定結果を通知する必要があるかもしれません
(>>269)。

[234] 
[[HTML]] や [[RTF]] など、[[文書形式]]自体に[[文字コード]]決定の機構が組み込まれているものもあります。
[SEE[ [[HTMLにおける文字コード]] ]]
それを尊重するものもあれば、
敢えて無視するもの、
上書きして指定できるものもあります。

;; [272] 
処理の途中で[[文字コード]]の指定を検知して、その場で入力[[文字コード]]を切り替える仕組みが必要となる場合もあります
(>>269)。


[235] 
[[フォント依存符号化]]を使った [[HTML]] や [[RTF]] のように[[文字コード]]の指定が多層的になる場合もあります。
通常は上層は記述された[[フォント名]]により自動的に決まりますが、
上層まで含めた全体の[[文字コード名]]が指定された場合の処理、
上層の[[フォント名]]が実態と合っていないため無視して上書きする動作オプションの提供など、
実装上考慮するべき特殊ケースもあります。

[236] 
原理的に [[RTF]] で使いようがない[[文字コード]]など、
[[文字コード]]の指定と[[文書形式]]の指定が矛盾する組合せが存在するため、
実装上は注意が必要になります。


** 変換可能性の判定


[145] 
[[文字コードの変換]]の操作と関係して、[[文字コードの変換]]が可能かどうかを決定するという操作が必要となる場合がたまにあります。

- [146] [[MIME]] は [CODE[charset]] について「最小公倍数」を指定することを求めていました。
例えば [[ASCII文字]]のみで構成されるなら、 [CODE[ISO-8859-1]] よりも [CODE[US-ASCII]]
と指定するのが良いとしていました。 [SEE[ [[charset最小化]] ]]
- [147] [[日本]]市場向けの [[MUA]] の中には通常は [CODE[ISO-2022-JP]]
を使い、それで表せない[[文字]]が含まれる時 [[UTF-8]] を使う機能を有するものがあります。
- [148] [[エディター]]類の中にはファイルの保存時等に出力[[文字コード]]で記述できない[[文字]]が含まれる場合に、
その旨の警告を表示したり他の[[文字コード]]の選択を促したりする機能を有するものがあります。

[149] 
こうした機能は実際に変換を行いながらエラーを検出する形で実装される場合もあれば、
事前に高速に判定する手法により実装される場合もあります。
どちらが好ましいかは使い方によりますが、後者の場合は実際の変換処理と乖離するリスクがあります。


* 変換の構成要素

[325] 
変換処理の実装戦略は様々ですが、その性格はいくつかの要素に分解できます。

** 1対1対応


[50] 
[[一対一対応]]が存在する場合、入力を機械的に変換して出力するだけですから、
変換器は非常に単純になります。

[51] 
すべての[[符号]]が[[一対一対応]]可能な[[文字コード]]体系間の変換は、
宣言的な変換表を用意して外部化することで、容易に対応体系を増やすことができます。

[49] 
[[平成時代]]初期くらいまでに欧米企業が進出していた地域の標準的な[[文字コード]]の[[文字]]のほとんどは、
[[Unicode]] と[[一対一対応]]が存在します。
また、同じ地域の同じ言語を対象とする他の[[文字コード]]とも[[1対1対応]]が存在する[[文字]]が多いです。


** 1文字対多文字対応

[52] 
ある[[文字コード]]で1文字として扱えるものが、他の文字コードでは複数の文字の列になることがあります。

[EG[

[53] 
例えば地域の[[文字コード]]ではアクセント付きで1つの[[文字]]で表せたものが、
[[Unicode]] では[[基底文字]]と[[結合文字]]の組合せとして表現するほかないことがあります。

]EG]

[54] 
[[一対一対応]]限定の実装より少し面倒になりますが、容易に実装できます。

[59] 
[[西暦1990年代]]初頭頃に欧米企業が実装していなかった[[文字コード]]にある[[文字]]は、
それが他の [[Unicode文字]]の組合せで表現できると判断された場合 [[Unicode]]
に追加されないことがほとんどなので、
それらから [[Unicode]] への変換でこのパターンとなります。


** 多文字対1文字対応 / 多文字対多文字対応

[55] 
ある[[文字コード]]で複数の文字の列で表されるものが、他の[[文字コード]]では1文字となることがあります。

[56] 
複数の文字のそれぞれが変換先の[[文字コード]]にも存在するなら、
[[1対1対応]]とみなして単純に変換することも可能です。

[57] 
複数の文字のいずれかが変換先の[[文字コード]]に存在しないなら、
文字列を1文字に変換する必要が出てきます。

[EG[

[58] 例えば[[基底文字]]と[[結合文字]]の組合せが入力されたとき、
[[結合文字]]に相当する[[文字]]が変換先にないなら、
組合せと同等の[[文字]]に置き換えないといけません。

]EG]

[61] 
入力があってもすぐに変換先を確定できず、数文字読み続けて適切な出力文字を選ぶ必要が出てきますから、
変換処理は複雑になってきます。


[60] 
1文字対多文字対応の変換の逆方向でこのパターンとなります。

-*-*-

[62] 
ある[[文字コード]]で複数の文字の列で表されるものが、
他の[[文字コード]]では複数の文字の列で表され、
両者の構成する文字それぞれに直接的な対応関係がないことがあります。

[63] 
[[インド系文字の文字コード]]などと [[Unicode]] との変換のように、
なにを[[符号化文字]]の単位とするかの考え方に大きな違いがある場合に、
この種の変換が頻出することになります。

[64] 
変換処理は相当に複雑になります。

** 文字の削除

[257] 
入力[[文字コード]]の文字(列)が完全に削除されることがあります。

- [258] [[インド系文字の文字コード]]などで表示上の位置調整など本質的な[[文字]]データを構成しない[[文字]]が含まれることがあり、
これが不要な[[文字コード]]への変換で削除されます。
- [259] 多段変換の途中で便宜上の[[文字]]が挿入されることがあり、
不要になった段階で削除されます。

** 変換対象部分文字列の条件

[277] 
ある[[文字コード]]の文字(列)から他の[[文字コード]]の文字(列)への変換が、
入力[[文字コード]]の文字(列)の複雑な条件という形で記述・実装されることがあります。

[278] 
汎用の[[正規表現]]エンジンで実装されることもあれば、
独自の[[状態機械]]などの形で実装されることもあります。

[279] 
固定長ではない文字列になることもあります ([CODE[+]], [CODE[*]] など)。

[280] 
記述には[[文字クラス]]が使われることもあります。
[[文字クラス]]の[[否定]]が使われることもあります。
1文字だけの小さな[[文字クラス]]もあれば、
十数万字の大きな[[文字クラス]]になることもあります。

[281] 
記述には選択 ([CODE[|]]) が使われることもあります。

[283] 
記述形式によっては[[文字列]]や[[空文字列]]も[[文字クラス]]の[[要素]]とできることがあります。
実効上は選択と等価です。


[282] 
[[文字クラス]]や選択は基本的には複数の置換規則に展開できます。
ただ[[文字クラス]]の展開は文字数が多すぎて現実的でないこともあります。


*** 変換対象部分文字列の可変部分の置換

[286] 
対象部分文字列のうちの一部分が、置換先で使われることがあります ([[capture]])。
実例をみていくと、

- [287] 順序の入れ替えの規則の記述に使われている場合
- [288] 前方一致や後方一致の条件として記述されている場合
- [289] ある文字の前後で使われる文字列の組合せを置換したい場合

のような用途があるようです。

[291] 順序入れ替えのように、置換前と置換先とで出現順序が変わることも少なくありません。

[292] 
1つの変換の条件で出現する [[capture]] の数は1個、2個程度のものが多く、
5,6個に達するものは珍しいようです。

-*-*-

[290] 
対象部分文字列が[[文字クラス]]や選択で記述されているとき、
置換先では[[写像]]からそれに対応付けられた[[文字]]を選ぶ形になっていることもあれば、
部分文字列だけに適用される規則群の形で記述されていることもあります。

*** 変換対象部分文字列の前方一致と後方一致の条件

[98] 
ある[[文字コード]]の文字(列)から他の[[文字コード]]の文字(列)への変換が、
入力[[文字コード]]の文字(列)とその前後の文字(列)の条件という形で記述・実装されることがあります。

[99] 
単純な多文字からの変換に置換できる場合も多いですが、
それでは変換表が巨大になりすぎてしまう (数千から無限大の規模となる) とき、
[[先読み]]・[[後読み]]のような手法で実装されることになります。

[100] 
条件部は固定長ではない文字列になることもあります ([CODE[+]], [CODE[*]] など)。

[262] 
条件部の記述には[[文字クラス]]が使われることもあります。
[[文字クラス]]の[[否定]]が使われることもあります。
1文字だけの小さな[[文字クラス]]もあれば、
十数万字の大きな[[文字クラス]]になることもあります。

[284] 
条件部の記述には選択 ([CODE[|]]) が使われることもあります。

[285] 
記述形式によっては[[文字列]]や[[空文字列]]も[[文字クラス]]の[[要素]]とできることがあります。
実効上は選択と等価です。


[101] 
条件部は文字列先頭、文字列末尾、[[語境界]]、[[空白]]といった形で記述・実装されることも多いです。
こうしたものは[[語頭形]]や[[語末形]]のような文字列中の文字の位置によって変換を制御する必要がある場合に使われがちです。

[260] 
条件部は一致するべき条件が記述されることもあれば、
一致しないべき条件が記述されることもあります。

[261] 
一致する、しないの条件と先頭・末尾・境界が一致するかしないかは、
条件の記述方法や[[正規表現]]エンジン等の利用方法によって変わってくるので要注意です。

*** メモ

[102] 
いずれの場合も変換処理は相当に複雑になります。

[103] 
意図を正確に記述できているのか疑問が残る実装も散見されます。

[104] 
>>101 のように本来同等の条件を意図していたと思われるものが実装ごとに違った形で記述されていることもよくあります。
同じような条件を移植していても、[[プログラミング言語]]等で挙動が微妙に異なると思われるケースもあります。

;; [263] 
[[文字クラス]]の定義、
[[境界]]の定義、
[[非決定的]]な挙動などが実装手法によって変わりがちです。

[105] 
実装の正しさの評価や他の実装との比較が困難になりますから、
可能であれば避けるべきなのでしょうが、避けることが困難と思われるケースも多いです。

** 1対多対応

[65] 
入力[[文字コード]]の1つの[[文字]]に相当する出力[[文字コード]]の文字(列)に複数の候補がある場合があります。

[66] 
出力の文字(列)が互いに同等なら、どれを選ぶかは実装者の任意の選択となります。
[[ライブラリー]]の類なら[[応用]]に動作オプションとして指定させる場合もあります。
[[プラットフォーム]]等で慣習が成立している場合もあります。
慣習とならず[[相互運用性]]の問題が起こることもあります。

[EG[
[67] [[Unicode]] への変換で、
[[基底文字]]と[[結合文字]]の組合せを出力するか、
[[合成済み文字]]を出力するかの選択肢が存在することがあります。
一般的には[[合成済み文字]]が適切と考えられていますし、
1対1対応の変換にできるので実装も単純化できます。
]EG]

[EG[
[68] 
[[Unicode]] に似た字形の[[記号]]がいくつもあり、
いずれを選択するか実装によって違いがあって[[相互運用性]]の問題となっている場合があります。
]EG]

[70] 
出力の文字(列)が同等とはいえないなら、どれを選ぶかは文脈その他によって決めることになります。

[71] 
前後の文字列との組合せで決められるなら多文字対多文字対応のような形で変換できますが、
多くの場合は機械的に選択することが困難です。

[72] 
機械的に決定できなければ、不適切な場合があることを承知の上でどれかを選ぶか、
[[GUI]] による選択などの手段で個々に決めるなどの方法になります。


[73] 
多くの場合はデータの劣化を恐れずどれか1つを選んで機械的に対応付ける方法を採っているようです。

;; [74] 
そうした関係性によって旧来の[[文字コード]]における[[文字]]の弁別や選定の慣習が
[[Unicode]] にも持ち込まれている事例が多々あると思われます。
元々旧来の[[文字コード]]は当該地域や言語の[[文字]]の選択の慣習を反映して開発されているでしょうから、
[[Unicode]] がそれと異なる基準で[[文字]]を収録していたとしても、
[[Unicode]] の基準が現地の運用に耐えられるとは限らないわけです。


[69] 
実装ではなく [CITE[Wikipedia]] の記事の対応表などでは、
複数の対応先の候補を併記する形を採っていることがあります。

** 多対1対応

[75] 
入力[[文字コード]]の複数の[[文字]]に相当する出力[[文字コード]]の文字が1つとなる場合があります。
いくつかに分類できます。

- [76] 
入力の各[[文字]]が同等である、つまり[[重複符号化]]の場合
- [77] 
入力の各[[文字]]が似た意味を持ち、入力の[[文字コード]]では用法を細かく区別するが、
出力の[[文字コード]]では区別しない場合
- [78] 
入力の[[文字]]で出力の[[文字コード]]では表現できないものが、
表現できる似た[[文字]]に置き換えられる場合

[79] >>76 >>77 は実装上は大きな問題はなく、単純に変換すれば済みます。

;; [80] ただし、[[往復変換]]はできなくなることに注意が必要です。

[81] 
>>78 は [[Unicode]] から従来の[[文字コード]]への変換で実装されていることがあります。
[[best fit]] などと呼ばれることがあります。
変換で失われる情報をできるだけ少なくするための配慮として実装されたものでしょうが、
情報の損失がわかりにくくなるという問題があります。

[EG[

[84] 
例えば [[Unicode]] から[[シフトJIS]]に変換する [[Win32 API]] で [[best fit]]
を有効にすると、[[アクセント付きラテン文字]]がただの[[ラテン文字]]に変換されます。

]EG]

[82] 
また、 [[best fit]] 写像によって[[セキュリティー]]の問題が生じる事案も報告されています。
[SEE[ [[best fit]] ]]

[83] [[best fit]] は提供する場合でも動作オプションとするべきでしょう。


** 多段変換

[85] 
[[インド系文字の文字コード]]と [[Unicode]] との変換など[[符号化文字]]の考え方が大きく異なる[[文字コード]]間の変換は、
1パスの単純な変換ではなく、複数回の変形処理の組合せとして実装されていることがよくあります。


[86] 
多段変換とすることで記述や実装が単純化することも多いですが、
どんな入力がどんな出力になるかの見通しは悪いことが多いです。


-*-*-

[156] 
機能的必然性がなく、実装の容易性のために多段化されているとみられる事例も散見されます。
例えば [[JavaScript]] で実装された変換器で、 [CODE[String]] の [CODE[replace]]
[[メソッド]]を繰り返し適用することで順次[[文字]]を置換していくようなスタイルの変換器が多数あります。

[157] 一昔前なら何パスも掛けて[[文字列]]を走査するのは無駄が多く、
1パスで文字列の先頭から順に見ていくのが良いとされたのでしょうが、
現在ではパフォーマンス上の違いは微々たるもので、
実装の簡単性と視認性のメリットが遥かに上回ります。
標準メソッドだけで記述できる分、独自にループで1パスで実装するよりも高速になる可能性までありますし、
実装ミスによる不具合のリスクも減ります。

[158] 
ただしこの手法は入力文字集合と出力文字集合が重ならない場合には安全ですが、
そうでない場合には置換の適用順序が重要になってきます。
ところがこれをあまり意識していないと思われる事例が散見されます。
出力が再度入力条件と一致することによる置換同士の相互作用が意図的と推定できる場合もあれば、
意図的なのかどうかはっきりしない場合も多いのです。
どちらにしても変換処理全体の入出力の関係が不明瞭となりがちで、不具合の温床となっています。
開発者自身が挙動を理解しきれず冗長な置換規則や誤った置換規則を挿入したと思しき事例もあります。

-*-*-

[253] 
変換の段 (pass, phase) 数は、
前述の通り実装戦略次第で1パスだったり数十から数百パスだったり様々となります。

[254] 
前述の [CODE[replace]] 鎖のような実装戦略の場合、
互いに干渉せず同時処理可能なものをまとめると高々二、三十パス程度になることが多いようです。
(もちろん一パスから二、三パス、せいぜい十パス程度に収まるものがかなり多いです。)
中には百数十パスくらいまでしか減らないものもありますが、
同時処理可能かどうかの判定が難しいケースを保守的に数えた結果ですから、
厳密に検討していけばもっと減らせるでしょう。

[255] 
[CITE[TECkit]] の [CODE[.map]] のように同時処理可能なものをまとめつつ人間の判断で分けた方が扱いやすいものを分ける実装戦略だと、
多くても十数パス程度になるようです。
[SEE[ [[.map]] ]]
人間により [CODE[.map]] で記述されたことがない[[文字コード]]の方が圧倒的に多いでしょうが、
おそらくこれを大きく上回る複雑さの[[文字コード]]は存在していないでしょう。



** 正規化処理

[87] 
変換処理本体の単純化のために別段で[[正規化]]の処理が適用されることがあります。

[88] 
入力が [[Unicode]] のとき、 [[NFC]] や [[NFD]] を適用することで、
変換処理本体が[[基底文字]]と[[結合文字]]の組合せか[[合成済み文字]]の一方だけを記述することで済ませたり、
[[結合文字]]の順序が入れ替わっている場合への対処を省略したりすることができます。


[89] 
入力が[[翻字]]系の[[符号化]]のときで[[大文字・小文字不区別]]のとき、
一括してどちらかに統一してから変換処理本体を実行する場合があります。

[90] 
入力の[[文字コード]]の構造上の理由から変換処理本体が[[基底文字]]と[[結合文字]]の組合せを出力したり、
[[合成済み文字]]を出力したりすることがあり、これを好ましくないと考える場合、
変換処理本体の後に [[NFC]] や [[NFD]] を適用する場合があります。

[91] 
こうした処理は変換処理本体の実装コストを削減できますが、
思わぬ副作用を生むこともあり、注意が必要です。

[EG[
[92] 
[[大文字と小文字]]の変換は[[プログラミング言語]]によって実装が違いますし、
[[ロケール]]によって違った変換となる場合もあります。
変換器の実装者がそうした詳細まで細かく注意して設計していないと思われる事例が散見されます。
]EG]

[256] 
なお、 [[Unicode正規化]]を実装しているかのような説明でありながら、
当該[[文字コード]]やその[[言語]]に関連がある部分だけしか実装していないようなものもあります。

** 順序入れ替え処理

[93] 
[[インド系文字の文字コード]]と [[Unicode]] の変換など、
[[符号化文字]]の考え方が大きく異なる[[文字コード]]の変換では、
入出力で[[文字]]の配列順序を変更しなければならないことがよくあります。

[94] 
入力または出力の数文字の部分文字列が特定のパターンに一致するかを判定し、
一致するなら順序を入れ替えるような処理を複数種類適用することになります。

[95] 
部分文字列の組み合わせ数が膨大過ぎて、
多文字対多文字対応に展開するのが事実上不可能な場合が多いです。

[96] 
実装によって、
出力[[文字コード]]への変換後に[[正規表現]]の置換を組合せたり、
[[正規表現]]の置換の組合せの後に出力[[文字コード]]へ変換したり、
出力[[文字コード]]へ変換しながら順序を入れ替える[[状態機械]]を実装したり、
内部処理用の中間表現を導入したりと、
様々な実装戦略が採られています。

[97] 
どの方法も相当複雑になりますし、概略同じ手法でも置換パターンの作り方次第で見かけ上の処理は大きく変わってしまいます。
従ってソースコードを読んで挙動を理解するのは至難の業ですし、
諸実装の特徴を比較することも困難です。

-*-*-

[242] 
[[ヘブライ文字の文字コード]]や[[アラビア文字の文字コード]]では[[論理順]]と[[視覚順]]の変換処理が必要となる場合が多いです。

[243] 
従来[[文字コード]]側だけでなく [[Unicode]] 側にも[[bidi]] 関係の制御の文字が多数あり、
それらの相互作用を考慮する必要があります。

[244] 
[[行]]の単位を検出し文字の順序を入れ替える必要があります。

[245] 
単純な逆順への入れ替えだけでなく、[[結合文字]]のように[[基底文字]]に付随する文字をグループ化するなど細かな調整が必要となります。

[247] 
実装戦略としては、

- [248] 狭義変換の前に実施する、
- [249] 狭義変換の後に実施する、
- [250] 狭義変換と組み合わさった処理として同時に実行する、

... の3通りがあります。
完全に分離する方がアルゴリズムとして綺麗でありメンテナンスが容易で不具合を生みにくいと考えられますが、
1パスで処理したい、 >>244 や >>245 のような複雑な処理との組合せで >>250
の方が実装しやすいという状況もあるのでしょう。

[246] 
[CITE[TECkit]] の [CODE[.map]] のように事前または事後に行うべき処理として分離している記述形式もあります。

[251] 
[[文字コードの変換]]の処理から[[視覚順]]と[[論理順]]の処理を敢えて除外することもあります。

[EG[
[252] 
[[Webにおける文字コード]]の処理では[[視覚順]]の [[ISO-8859-8]] を
[[Unicode文字列]]に[[変換][文字コードの変換]]する際に[[論理順]]にせず元のままにして、
[[CSS]] によって[[表示][文字のレンダリング]]する際に通常の [[bidi]] の規則を適用せずそのままの順序としています。
[SEE[ [[ISO-8859-8]] ]]
]EG]


** アルゴリズム的変換

[109] 
[[文字コードの変換]]の処理で変換表の類によらない計算のみで実現できる操作はいろいろあります。
例えば、

- [110] [[ISO/IEC 2022]] における [[GL]] と [[GR]] の変換
- [115] [[ISO/IEC 2022]] における [[CR]] と [[[CN[ESC]] [VAR[Fe]]]] の変換
- [111] [[JIS X 0208]] に基づく[[シフトJIS]], [[日本語EUC]], いわゆる[[JISコード]]の変換
- [112] [[UTF-8]], [[UTF-16]], [[UTF-7]], [[SCSU]], [[BOCU]], [[UTF-1]] などの変換
- [116] 情報交換用符号を符号空間に配置した各種[[内部符号]]との変換
- [117] [[同型符号化]]・[[同型復号]]
- [113] [[Punycode]] などの変換
- [114] [[escape]] との変換

-*-*-

[106] 
[[平成時代]]初期ごろまでの[[日本]]の[[文字コードの変換]]は、
[[JIS X 0208]] に基づく[[シフトJIS]]と[[日本語EUC]]といわゆる[[JISコード]]の変換が中心で、
簡単な計算で相互に変換できました。

[107] 
その後 [[Unicode]] の普及期には、計算で変換できず数千行の変換表が必要となる
[[Unicode]] と従来[[文字コード]]との変換は敬遠されがちで、 [[Unicode]]
移行の障害となっていました。

[108] 
[[Unicode]] が一般化した現在では、計算機性能の向上もあってこうした問題が意識されることはなくなりました。
しかし[[シフトJIS]]と[[日本語EUC]]といわゆる[[JISコード]]の変換も [[Unicode]] を介して行われることが増え、
[[Unicode]] との対応関係がそれぞれ微妙に異なるために従来なら無劣化で行えた変換でデータ損失が生じるような事態も生じています。

** 入力符号の状態

[204] 
[[文字コードの変換]]の実装は、入力を読み込みながら、
入力[[文字コード]]の状態を管理する必要があります。

[205] 
入力の状態の例:

- [208] 複数の[[バイト]]で構成される[[符号]]の読み取り状態
- [209] [[エスケープシーケンス]]の読み取り状態
- [210] [[制御機能]]の読み取り状態
- [206] [[ISO/IEC 2022]] の状態
- [207] [[TRONコード]]の状態
- [265] [[漢字イン]]・[[漢字アウト]]の状態
- [266] その他[[文字コード]]体系独自の状態
- [264] [[翻字]]・[[転写]]の手法が規定するモード切り替えや[[括弧]]の対応など
- [211] [[結合文字列]]その他の[[合成文字]]を構成する[[文字]]の列の読み取り状態
- [220] [[[CH[˥˩]]]], [[[CH[˩˥]]]]
- [221] [[国旗絵文字]]
- [223] [[PVS]]
- [224] [[escape]]
- [213] [[行]]その他[[端末]]の状態
- [222] [[単語]]における位置
- [214] [[bidi]] の状態
- [215] [[書式制御文字]]の状態
- [216] [[タグ文字]]の状態
- [217] [[言語情報]], [[ロケール]], [[フォント]]
- [218] [[太字]], [[斜体]], [[打ち消し線]], その他
- [219] [[文字列]]に埋め込まれた[[文字]]ではないオブジェクト

-*-*-

[212] 
[[Unicode正規化]]から呼び出される[[正準再順序付け]]のように無限の長さの文字列の状態を保持しなければならない処理があります。

[237] 
[CITE[TECkit]] の [CODE[.map]] は [CODE[+]] や [CODE[*]] などによる任意の長さの[[列]]を条件として記述していますが、
一致する最大長を [N[15]] [[以下]]に制限しています。

[238] 
同じような条件の記述でも、このような長さ制限を設けていないで[[正規表現]]の実装に任せたり、
自前でも[[状態機械]]により無限の長さを[[受理]]したりする実装も多いです。

[239] 
[[自然言語]]の記述である[[文字]]の列であれば、そうした余りに長い[[文字列]]が出現することはまずないと考えられるので、
[N[15]] など[[現実的な長さに制限することは合理的な実装上の配慮であり、セキュリティーその他のために望ましくもあります][ハードウェア制限条項]]。


[240] 
こうした長さの上限のない変換条件の記述は、
[[音節]]の単位を検出しつつ置換や順序入れ替えを実施したい[[インド系文字の文字コード]]の変換処理や、
[[行]]単位で順序の入れ替えを実施したい[[ヘブライ文字の文字コード]]や[[アラビア文字の文字コード]]の[[論理順]]と[[視覚順]]の処理、
[[語頭形]]・[[語中形]]・[[語末形]]の処理などで見られます。

;; [241] 
[[文字コードの変換]]以外では [[shaping]] や[[結合文字列]]など[[文字のレンダリング]]の関連の処理で似たような状況が出現します。

-*-*-

[267] 
実装によっては[[文字コードの判定]]や[[翻字]]・[[転写]]の体系とただの [[English]]
の区別の確立的判定など、符号化手法を判断する処理と変換の処理が結合していることがあります。

[268] 
更には [[HTML]] の[[文字コード]]指定の[[検知][charset sniffing]]のような[[文書形式]]や[[プロトコル]]に依存した処理も併合されていることがあります。

[269] 
[[HTML]] における[[符号化の変更]]の処理など、[[文字コードの判定]]の結果を報告したり、
それに応じて[[文字コードの変換]]の処理を再起動したりといった措置が必要になることもあります。

** 状態付き符号への変換

[150] 
出力[[文字コード]]が状態を持つことがあります。

[151] 
例えば出力が [[ISO/IEC 2022]] に基づき複数の[[符号化文字集合]]を切り替えて使える[[符号]]の場合、
変換は入力文字符号から状態と文字符号の組への[[写像]]の形で記述されることになります。
出力の状態が現在の状態と同じならそのまま文字符号を出力でき、
現在の状態と異なるなら状態を切り替えてから文字符号を出力することになります。

[152] 
同じ入力文字符号に対する出力の候補として、複数の状態とその文字符号がある場合があります。
この場合、現在の状態と同じものがあれば、その候補を選択すると、自然な出力となる場合が多いです。
(出力[[文字コード]]の仕様や慣習にも依存します。)

[EG[
[153] 
例えば [[Unicode]] から [[ISO/IEC 2022]] に基づき [[JIS X 0208]] と [[GB 2312]] を使える[[符号]]へと変換する場合、
[CH[一]]は [[JIS X 0208]] と [[GB 2312]] のどちらにも存在するので、
現在の状態に応じてどちらを使うかを決めれば、切り替えのための[[指示シーケンス]]を節約できます。
]EG]


[154] 
出力の状態切り替えは、 [[ISO/IEC 2022]] の[[エスケープシーケンス]]のような[[文字コード]]層の技術による場合もあれば、
[[HTML]] の [CODE[font]] [[要素]]や [[RTF]] の[[フォント]]切り替えのような[[文書形式]]の機能によって行う場合もあります。

[EG[

[155] 
[[エチオピア文字の文字コード]]や[[チベット文字の文字コード]]や[[ギリシャ文字の文字コード]]など、
変換処理が入力の[[フォント]]の違いを認識したり、出力の[[フォント]]を切り替えたりする必要のある構造のものがあります。

]EG]


** 変換されない部分文字列

[326]
入力の部分文字列がそのまま出力されることがあります。

[327] 
入力[[文字コード]]と出力[[文字コード]]で同じ表現になる[[文字]]がある場合があります。

[EG[
[328] 多くの[[文字コード]]体系は [[ASCII文字]]を同じ[[バイト列]]で表します。
]EG]

[329] 
入出力がほぼ同じでも、[[バイト列]]と[[文字列]]のような[[データ型]]の違いだけがある場合があります。
そうした場合の処置は[[プラットフォーム]]によって異なります。

;; [330] [[暗黙の型変換]]が行われる[[プログラミング言語]]等もあります。
そうした機能性を活用するときは意図せぬ[[型変換]]による[[不具合]]への注意も同時に必要となります。

;; [331] [[UTF-8]] の[[バイト列]]から内部表現 [[UTF-8]] の[[文字列]]へ、
通常行われる検査を省略して高速に変換する [[API]] を持つ[[プログラミング言語]]等もあります。
そうした機能を使う場合、不正な入力を無理に[[文字列型]]に[[キャスト]]してしまい、
以後の処理が誤作動したり、暴走したり、[[セキュリティー]]の問題を起こしたりすることがないよう、
最新の注意が必要となります。


[332] 
[[フォント依存符号化]]の変換器のように、対象外となる部分は無変換とすることがあります。


-*-*-


[333] 
[[ASCII]] と[[8ビット符号]]で構成される[[文字コード]]であることを前提に、
[[ASCII文字列]]なら[[文字コードの変換]]の処理を省略し、
そうでないなら[[文字コードの変換]]の処理を実行するような性能向上のための最適化が行われることがあります。

[334] 
こうした最適化は、例えば[[多バイト符号]]の第2バイトに [[ASCII文字]]と同じ[[バイト]]が含まれる場合や、
[[ISO-2022-JP]] のような[[7ビット符号]]など、設計者の想定不足による不具合を起こすことがありますから、
十分に注意が必要です。



** 変換不能な入力への対処

[118] 
入力となる[[文字コード]]の[[文字列]]であるはずのものには、
適切に変換できないデータが含まれていることがあります。

[119] 
具体的には

- [120] 入力[[文字コード]]の仕様上出現しないはずの[[バイト列]]
- [121] 入力[[文字コード]]の構造上は存在するものの、[[符号化文字]]の割当がない空き領域に相当するもの
-- [122] そのうち、新しい版など関連する他の[[文字コード]]では割当があるもの
- [135] 
入力[[文字コード]]では正当な[[文字]]だが、出力[[文字コード]]で表せないもの

といったものが考えられます。

[123] 
歴史的に[[文字コード]]関連規格は不正な入力への対処を明確に規定して来ませんでした。
こうしたものに遭遇したときの仕様上の「正しい」挙動が存在しないことが多いです。

[124] 
近年の [CITE[Encoding Standard]] はあらゆる入力に対する挙動を定めていますが、
例外的な存在です。

[125] 
こうしたデータに対する処理は実装によって様々です。

- [126] 動作オプションを指定できるもの
- [127] [[置換文字]]等に置き換えるもの
- [225] [[画像]]その他の[[文字]]ではないオブジェクトや[[文字]]と[[文字]]でないオブジェクトの組合せや[[文字]]と書式その他の付加情報の組合せに置き換えるもの
- [128] [[escape]] 類に置き換えるもの
- [134] 関連する他の[[文字コード]]とみなして処理するもの (>>122)
- [143] 似た文字に置き換えるもの (>>81)
- [129] エラーとして停止するもの
- [130] 入力をそのまま出力するもの
- [131] 何も出力しないもの
- [132] 異常停止するもの、異常動作するもの

[133] 
このうち >>130 >>131 >>132 は[[セキュリティー]]上の問題を起こしかねないですし、
>>129 も[[ライブラリー]]等で[[応用]]の開発者が意図していない場合には好ましからざる挙動となることがあります。
不適切なデータに対する挙動はあまり意識されないことが多いようで、
このような問題を孕んだ実装は意外と多いです。

[136] 
ただし出力先が [[HTML]] や [[RTF]] などで[[フォント]]指定を伴う場合のように、
>>130 が正当な選択肢となることもあります。

[203] 
[[エディター]]類でファイルを開く場合のように、不正な入力も生の[[バイト]]として他の[[文字]]とは区別してそのまま保持できることが好ましい用途もあります。



[179] 
[[置換文字]]や [[escape]] に置き換える手法は非常によく用いられますが、
通常の入力からの変換結果との区別に注意が必要となることがあります。
例えば不正な入力を [CH[?]] に置き換えると、
本来の [CH[?]] と区別が付かなくなり、問題となる場合もあります。

[180] 
多数の[[文字コード]]の出力に対応する実装や外部から動作オプションで指定できる実装は、
[[置換文字]]や [[escape]] が出力先の[[文字コード]]に存在しない[[文字]]を含む場合の対処にも注意が必要です。

[293] 
変換表の類は、明示的な変換規則がない場合に使われる[[置換文字]]を記述できるようにしているものも多いです。

[294] 
変換表や実装などが採用している[[置換文字]]の例:

- [295] [CC[U+FFFD]]
- [297] [CC[U+0020]]
- [300] [CC[U+001A]]
- [298] [CH[〓]]
- [299] [CH[・]]
- [296] [CH[?]]


* 往復変換

[306] 
変換直後に逆変換することを合わせて[DFN[[RUBYB[往復変換][roundtrip conversion]]]]といいます。

[307] 
[[文字コードの変換]]に限った用語ではありませんが、[[文字コード]]について使うことがかなり多いようです。


[308] 
[[往復変換]]は[[文字コード]]の性質や[[文字コードの変換]]の性質の評価において重要な観点です。

[319] 
[[往復変換]]の成否は個別の[[文字列]]についていう事もあれば、
[[文字コード]]体系全体を総括的にいうこともあります。



-*-*-

[309] 
[[Unicode]] は欧米の主要な[[文字コード]]の[[文字]]をすべて収録しているため、
そのような従来[[文字コード]]から [[Unicode]] に変換し、
従来[[文字コード]]に戻すような[[往復変換]]では情報の損失がほとんど発生しません。

;; [310] 
[[20世紀]]末から[[21世紀]]初頭の[[プラットフォーム]]は保存データが従来[[文字コード]]、
内部処理用が [[Unicode]] という方式のものが多かったので、
[[往復変換]]の安全性が重要でした。

[311] 
[[往復変換]]の安全性は、逆転させると違うことがあります。

[EG[

[312] >>309 の場合でも、 [[Unicode]] から従来[[文字コード]]に変換し、
更に [[Unicode]] に変換すると、情報の損失が発生することがあります。

]EG]


[313] 
[[アジア]]の多くの[[文字コード]]は >>309 の性質が成り立たないか、
成り立つか自明ではありません。

[314] 
個別の実装をみても、順方向と逆方向で処理が対照的になっていない事例が散見されます。
それが意図的なものかそうでないのか、
特定の実装の性質なのか[[文字コード]]自体の性質かなど、
判断するのが困難な場合が多いです。
(そういう実装は複雑な変換処理を行っているものなので、判定が難しいです。)


-*-*-

[315] 
[[重複符号化]]は[[往復変換]]が成功しなくなる大きな要因です。

[317] 
[[文字]]の概念や[[符号化]]モデルが違う[[文字コード]]体系同士の変換だと[[往復変換]]が成功しないことが多くなると考えられます。

[318] 
扱う[[文字]]が異なる[[文字コード]]体系だと[[往復変換]]が成功しないことが多くなります。
一方にしかない[[文字]]があると当然失敗します。





-*-*-

[316] 
[[往復変換]]の安全性は[[文字]]レベルの情報の損失を基準に議論されることが多いようです。
[[バイト]]レベルで複数の表現があり得る[[文字コード]]体系だと[[往復変換]]によって異なる[[バイト列]]となることがあり、
それを[[往復変換]]が成功した、していないと議論されることはあまりないように思われます。


-*-*-

[320] 
変換表の形で記述される変換は[[往復変換]]を前提にしたものが多いです。

[321] 
[CITE[TECkit]] の [CODE[.map]] のように複雑めな変換を記述できる形式でも、
順方向と逆方向の変換をセットで記述し、共通部分と差分を含められるようにしている場合があります。


* 変換用の写像表


[35] 
[CITE@en[CodepageEncoder/data/encodings at main · NielsLeenheer/CodepageEncoder · GitHub]], [TIME[2025-05-23T15:52:48.000Z]] <https://github.com/NielsLeenheer/CodepageEncoder/tree/main/data/encodings>


-[36] [CITE@en[icu/icu4c/source/data/mappings at main · unicode-org/icu · GitHub]], [TIME[2025-05-29T12:29:56.000Z]] <https://github.com/unicode-org/icu/tree/main/icu4c/source/data/mappings>
-[37] [CITE@en[icu-data/charset at main · unicode-org/icu-data · GitHub]], [TIME[2025-05-31T11:52:53.000Z]] <https://github.com/unicode-org/icu-data/tree/main/charset>
- [38] [CITE@ja[ICU - International Components for Unicode - Character Set Mapping Tables]], [TIME[2025-05-31T11:53:44.000Z]] <https://icu.unicode.org/charts/charset>


[39] [CITE[Evertype: Unicode Mapping Tables]], [TIME[2006-01-01T14:10:51.000Z]], [TIME[2025-06-06T14:32:00.732Z]] <https://www.evertype.com/standards/mappings/>


[40] 
[CITE@en-US[sourceware.org Git - glibc.git/tree - iconvdata/]], [TIME[2025-06-25T13:02:45.000Z]] <https://sourceware.org/git/?p=glibc.git;a=tree;f=iconvdata;h=494f8c50b9c9662ae85bf56184db943b0526e12c;hb=b2a8d19f4adc8ca22394b02c144b4bc867adc804>


[10] [CITE@ja[xorg / font / encodings · GitLab]], [TIME[2025-09-12T10:22:04.000Z]] <https://gitlab.freedesktop.org/xorg/font/encodings>

-[11] [CITE@en[xterm-snapshots/charsets.dat at master · xterm-x11/xterm-snapshots · GitHub]], [TIME[2025-09-12T10:30:35.000Z]] <https://github.com/xterm-x11/xterm-snapshots/blob/master/charsets.dat>
--[12] [CITE@en[xterm-snapshots/charsets.h at master · xterm-x11/xterm-snapshots · GitHub]], [TIME[2025-09-12T10:31:19.000Z]] <https://github.com/xterm-x11/xterm-snapshots/blob/master/charsets.h>


** Unicode Consortium の変換表

[8] 当初は [[FTP]] 配布 [SEE[ [[Unicode Consortium]] ]]

[20] [CITE[General Questions about Chararcter Mappings]], [TIME[2025-06-30T04:33:44.000Z]], [TIME[1997-01-05T19:42:04.261Z]] <https://web.archive.org/web/19970105193228/http://stonehand.com:80/unicode/faq/mappings/general.html>

[21] 
[CITE[Questions about Mapping Tables]], [TIME[2025-06-30T04:34:20.000Z]], [TIME[1997-01-05T19:42:29.061Z]] <https://web.archive.org/web/19970105193219/http://stonehand.com:80/unicode/faq/mappings/tables.html>

** [CITE[Encoding Standard]] の変換表

[SEE[ [[Encoding Standard]] ]]

** [CITE[TECkit]] の [CODE[.map]] ファイル

[SEE[ [CODE[.map]], [[TECkit]] ]]

* 文脈

[FIG(list middle)[ [9] [[文字コードの変換]]

- [[Webにおける文字コード]]
-- [CITE[[[Encoding Standard]]]]
- [[SGMLにおける文字コード]]
- [[XMLにおける文字コード]]
- [[ファイル名の文字コード]]

]FIG]

* 実装

[FIG(list middle)[ [196] [[文字コードの変換]]の実装

- [CITE[iconv]]
- [CITE[nkf]]
- [CITE[hc]]
- [CITE[hmconv]]
- [CITE[hcode]]
- [CODE[jcode.pl]]
- [CODE[Jcode.pm]]
- [CODE[Encode.pm]]
- [CITE[lv]]
- [CITE[Emacs]]
- [CITE[w3m]]


]FIG]


* 研究史

[170] 
個別の[[文字コード]]対の変換操作については[[20世紀]]から[[21世紀]]初頭の頃に実装戦略が研究されてきているものの、
[[ソースコード]]以外にまとまった文章の形となっていない場合が大多数と思われます。

[171] 
各種の[[文字コード]]技術の変換を包括的に議論したものはほとんどないと思われます。
あるとしても[[欧米]]や[[東アジア]]の主要な[[文字コード]]規格に関するものが中心で、
[[アジア]]等の各地で使われた[[フォント依存符号化]]系の変換技術や [[HTML]], [[RTF]]
の処理と組み合わさった変換技術、[[ワープロ]]の[[マクロ]]の形の実装手法など、
本格的な研究対象として観察されてこなかったと思われる領域が多いです。

[172] 
実装技法も実装そのものも [[Unicode]] への移行の進展と共に忘れられつつあり、
技術史の観点から個々の実態調査を進めて全貌を究明し、
要素技術を整理して検証していくことが急務でしょう。



* 関連

[7] [[変形]], [[符号化]]、[[復号]], [[文字コード判定]],
[[文字コードの修復]]

* メモ


[165] 
変換器は古今東西に無数に開発され利用されてきたようです。

[166] 
その中には十分なテストがされておらず満足に動作しないもの、
致命的な不具合があるもの、
意図した動作なのか疑わしい挙動をするものもあります。

[167] 
驚くべきことに、地域コミュニティーの中心的な Web サイトの変換器であってもそのような品質のものが珍しくありません。

[168] 
また、同じ[[文字コード]]体系に対応していると主張する変換器同士であっても、
互いの挙動に違いがあることは珍しくありません。
どちらが正しいか判断できないもの、どちらも違った形で壊れていると思われるものも多いです。

[169] 
単純な変換表の形で表現された変換器の実装や明らかに単純な変換をしている変換器の出力なら互いに比較することもできますが、
複雑なアルゴリズムで変換しているものは、[[ソースコード]]を慎重に読み込んでも互いの挙動にどのような違いがあるのか理解しづらいことがほとんどです。


- [30] [CITE[telecode(5)]], [TIME[1998-10-14T23:29:58.000Z]], [TIME[2022-05-03T03:38:56.992Z]] <http://www2.phys.canterbury.ac.nz/dept/docs/manuals/unix/DEC_4.0e_Docs/HTML/MAN/MAN5/0330____.HTM>
- [31] [CITE[Microsoft Word - Chinawrd.doc - CHINPRN.PDF]], [TIME[1999-06-21T12:00:00.000Z]], [TIME[2022-05-03T06:55:10.367Z]] <http://www2.phys.canterbury.ac.nz/dept/docs/manuals/unix/DEC_5.0a_Docs/ACRO_SUP/CHINPRN.PDF#page=33>

[201] [CITE@ja[3.15.7 Javaにおける文字化けの問題についての注意事項]], [TIME[2006-08-04T20:04:19.000Z]], [TIME[2025-11-19T14:46:58.392Z]] <https://software.fujitsu.com/jp/manual/manualfiles/M060036/B1WN6251/01Z201/note03/note0083.htm>

[202] [CITE[null]], [TIME[2025-11-19T14:48:49.000Z]] <https://docs.oracle.com/cd/E19253-01/819-0364/6n2q0anpf/index.html>
