[31] 
[[文字コード]]を[[識別]]する[[名前]]の体系には色々なものがあります。

* 識別子の体系

[24] 
各種の[[プロトコル]]や[[文書形式]]、
[[プログラミング言語]]や[[文字コードの変換]]の実装などでそれぞれ[[文字コード]]の[[識別子]]の体系を定めています。

[FIG(short list)[ [1] [[文字コード名]]の体系
- [[符号化名]]
- [[符号化ラベル]]
- [[UTR #22]]
-- [CITE@en-us[UTS #22: CharMapML]] ([TIME[2017-06-01 07:35:01 +09:00]]) <https://www.unicode.org/reports/tr22/tr22-8.html#Charset_Alias_Matching>
- [[IANA charset]] 名
- [[IANA charset]] [CODE[MIBenum]]
- [CODE[charset-edition]]
- [CODE[charset-extension]]
- [CODE[encoding=""]]
- [CODE[Encode.pm]] の名前
- [CITE[iconv]] の名前
- [CITE[ICU]] の名前
- [[.Net]] の Encoding 名
- [[Java]] の Charset 名
- [[Python]] の codec 名
- [[[CITE[Emacs]] の coding-system 名][coding-system]]
- [[[CITE[Vim]]の符号化名][Vimにおける文字コード]]
- [[MySQL]] の文字集合名
- [[ISO-IR登録番号]]
- [[公開テキスト指示シーケンス]]
- [[コードページ]]
- [[CCSID]]
- [[POSIXロケール]] 文字集合 (charmap 名) 
- [[XLFD]] 文字集合 (registry-encoding)
- [CODE[encodingID]]
-[[エチオピア文字符号化系引数値]]
- [[フォント名]]

]FIG]

;; [27] この他に、 [[UTF-8]] であることのみを示せる[[プロトコル要素]]などもあったりします。


[25] 
歴史的に見れば[[インターネット]]では [[IANA charset]] の影響力がかなり強いものの、
それ単独で用いるほどカバー範囲と定義の厳密性はなく、
各種の実装はそれを取り込みつつ各分野の従来の慣習と統合する形を採っており、
似て非なる体系が大量に生じています。


-*-*-

[20] 
[[数値符号]]を除けば、[[ASCII文字]]で構成されるものが多いです。

[21] 
稀に[[非ASCII文字]]が使われるものもあります。
[[文字コード]]の指定がなされる場面で[[非ASCII文字]]は安全に使えないことが多いので、
矛盾した状況にも思えますが、稀とはいえ現に存在します。
とはいえ多くは仕様上認められていない利用方法です。

[22] 
[[ASCII文字]]の諸記号は、どれを使えるか制限されていることもありますが、
守られていない場合もあります。
どれが使われるかは慣習によるところが大きいですが、
一貫しないものや体系によって違うものも多く、
統一的な基準は無いと考えて構いません。
無視したり統一したりする実装もありますが、
それによって名前が衝突する場合もあります。

[23] 
[[大文字と小文字]]は、区別しないことが多いです。
正規形が定義されていることもありますが、まず意味がないと考えて間違いありません。
実態としても様々な形で使われており、
文脈と個別の[[文字コード]]次第でどの書き方が多いという傾向は多少あれども、
強い慣習といえるものはありません。



-*-*-

[16] 
似た構造の[[文字コード]]に統一的な名称を与えようとした試みもありますが、
他の色々な名前が混在する中で統一的な命名規則を徹底するのは難しいようです。

[17] 
[CODE[charset-edition]] や [CODE[charset-extension]]
のように識別子を多次元化する試みもありましたが、成功していません。




-*-*-


[30] 
多くの[[文字コード]]は正式な唯一の名前が無かったり、
機械的な[[識別子]]としての利用に適した名前では無かったり、
人間向けと機械向けで違う名前を用意していたり、
識別子の体系によって違う名前を与えられていたりします。

[7] 
また、識別子の体系の管理が破綻していて、
正式な定義と実際に使われるものと違いが生じていたり、
正式な定義がないまま[[事実上の標準]]となるものが使われていたりすることもままあります。

[8] 
他の識別子の体系の識別子が移入されて使われることも多いのですが、
丸々同じものを採用せずにつまみ食い + 独自分、というパターンが非常に多いので、
[[利用者]]の正確な理解を妨げています。

[6] 
たまに識別子に含まれる些細な[[記号]]や[[空白]]の違いで「この文字コードをこれこれというのは誤りで、
これこれというのが正しい」と主張する人が出現しますが、
そのような主張は正しくないことが多いです。
「これこれの場面ではこれこれの名前が正しい」
のような限定的な条件でしか成立しないことを、勝手に拡大解釈するタイプです。

[10] 
より深刻な問題として、識別子が[[文字コード]]体系の細かなバリエーションのどれを指しているのか明らかでない場合や、
正式な定義と世間の実態が乖離している場合が多くあります。
識別子の体系が細かなバリエーションを区別しているのに、
実態としては混用されているような場合もあります。


[9] 
こうした問題は解決しないまま [[UTF-8]] への移行が進み、表立ってトラブルにつながることが少なくなったのはいいことですが、
一方で問題の発生数が減って見えにくくなったり、
古いデータやプログラムの理解に問題があるのを修正されないままとなっていたり、
トラブル解決のための情報が減少していたりと、
狭く深い問題に変化しつつあります。


[15] 
[[フォント依存符号化]]のように[[フォント名]]が事実上の[[文字コード]]の識別子となる場合もあります。




* 識別される「文字コード」




[12] 
[CN[BOM]] 有無など[[出力時の動作オプション][文字コードの変換]]に当たるものが[[文字コード名]]に取り込まれていることがあります。

[11] 
狭義の[[文字コード]]の体系の他に、[[改行文字]]の種別や [[Unicode正規化]]の適用などの[[動作オプション][文字コードの変換]]が[[文字コード名]]に取り込まれていることがあります。

[13] 
[[Base64]] など[[内容転送符号化]]や[[符号化語]] [[escape]]
のような[[文書形式]]や[[プロトコル]]の構文、あるいはそれと狭義の[[文字コード]]との組合せも
「文字コード」として名前が付与されていることがあります。

[28] 
[[照合順序]]との組合せに名前が付与されていることがあります。

[14] 
[[文字コードの自動判定]]も1つの「文字コード」として名前が与えられていることがあります。
判定法の違いにもそれぞれ名前が与えられていることがあります。

[26] 
単独で用いられる[[文字コード]]の他、[[エスケープシーケンス]]で切り替えられる[[符号化文字集合]]や[[フォント]]の記述に用いられる符号化など、
狭義の[[文字コード]]の体系といえるものの中にも性質が異なるものが混在しており、
識別子の体系はそれらを区別したりしなかったりしています。



[18] 
[CODE[x-user-defined]],
[[replacement]], 
[CODE[x-transparent]],
[CODE[default]] [SEE[ [[Vimにおける文字コード]] ]],
[CODE[prc]] [SEE[ [[Vimにおける文字コード]] ]],
[CODE[japan]] [SEE[ [[Vimにおける文字コード]] ]],
[CODE[raw-text]],
[CODE[no-conversion]],
[CODE[ASCII-8BIT]],
[CODE[undecided]],
[CODE[prefer-utf-8]],
[CODE[unknown-8bit]]
のように特殊な「文字コード」もあります。


[19] 
特殊な「文字コード」は特定の場面で認識され、特定の場面では認識されないなど、
扱いが通常の[[文字コード]]と違うことがよくあります。


* 最適な文字コードの選定


[32] 
[[文字コードの識別子]]を付けてデータを送出する実装は、
選んだ[[文字コード]]の名前をそのまま書くのかどうか判断を迫られる場合があります。
[[文字コード]]の選択と連動することもあれば、独立している場合もあります。

[33] 
ある[[文字コード]]が別の[[文字コード]]の[RUBY[[[部分集合]]][サブセット]]、という関係性が成立する組合せが多数あります。
ある[[文字コード]]と別の[[文字コード]]は全体としては互換性がないものの、
一部の[[ビット組合せ]]の割当は共通しているので、その範囲内ならどちらとしても解釈できる、
という組合せもいくつもあります。

[EG[

[34] 
[[MIME charset]] [CODE[US-ASCII]] は [[MIME charset]] [CODE[ISO-8859-1]] の[[部分集合]]です。

]EG]


[EG[

[35] [[ISO/IEC 8859-1]] と [[ISO/IEC 8859-15]] の[[符号化文字集合]]の[[ビット組合せ]]の大部分は共通です。

]EG]


[36] 
[[MIME]] は[[最小公倍数]]を選ぶように求めています (>>145)。
しかし具体的にどう選ぶべきかは決めておらず、実装に丸投げしています。 

[EG[

[37] [[MIME charset]] [CODE[US-ASCII]] よりも [[IANA charset]]
[CODE[ISO_646.basic:1983]] の方が更に[[部分集合]]ですが、
可能ならこれを使うべきなのかどうか定かではありません。

[38] 実際上は [CODE[US-ASCII]] とするべきと考えられますが、
明文規定上そう考えるべき理由は無さそうに思われます。


]EG]


[39] 
当時も今も、このような扱いづらい規定を厳密に適用している実装はさほど多くありません。


** charset 最小化

[145] 一般に [[MIME]] の生成ソフトウェアは、
[CODE[charset]] に可能な限り「[[最小公倍数]]」
たる[[文字集合]]を使うべきです [SRC[>>265]]
([DFN[charset最小化]])。

[EG[
[146] 例えば [CODE(charset)@en[[[ISO-8859-[VAR[X]]]]]] の[[左半分]]しか使わないなら、
[CODE(charset)@en[[[US-ASCII]]]] を使う[['''べきです''']] [SRC[>>265]]。
]EG]

;; [147] しかし現在となってはむしろ常に [[UTF-8]] を使う方が[[相互運用性]]は高いかもしれません。

[REFS[

- [265] [CITE@en[[[RFC 2046]] - Multipurpose Internet Mail Extensions (MIME) Part Two: Media Types]] ([TIME[2015-03-22 13:14:46 +09:00]] 版) <http://tools.ietf.org/html/rfc2046#section-4.1.2>

]REFS]

[102] [[MIME]] では未知の [CODE(MIME)@en[[[text/[VAR[*]]]]]] [[MIME型]]は
[CODE(MIME)@en[[[text/plain]]]] として扱うことになっています。
[CODE(MIME)@en[[[charset]]]] [[引数]]がこの際どう扱われるかは不明です。


[2] [[MIME charset]] の最小化規則と、 [[HTTP CGI]] のような動的生成って本質的に相容れないもののような気がしませんかね。あるいは streaming 的なものとも。 [[chunked符号化]]の尾っぽ header を使えば何とかならなくもない気もするけど, クライアント側で届いたところからレンダリングが不能になって結局意味がない (サーバー側でデータ生成完了後に charset を判定して一気に送りつけるのと変わらない) し、よって steraming には使いようがないし。
- [3] >>2 の解法は最小化規則をあきらめちゃうしかないのかな。 CGI 動的生成はまだ最大の範囲を知ってそうなものだけど、 streaming だと知らないこともあり得る (多言語会談とか?) から、考えうる最大の charset ([[UTF-8]] とか?) を予め仮定しておくしかなさそう。
- [4] >>3 の考え方はつまり charset 指定の最大化であって、 MIME の考えとは全く逆になってしまう。
- [5] >>4 そもそも MIME の最小化規則は相互通信性最大化を目的としている。 [[SMTP]]/[[822]] では基本的にやり直しが効かないから、一度で相手に伝える必要がある (概念上は)。一方 HTTP とかだと[[内容折衝]]もあるし、 (歴史的経緯のせいで) ブラウザの利用者の操作で文字コード選択が出来るから (メイラにもあるけど、 MIME の思想的には考慮外だと思う。) 一度で伝える必要性ってのはあんまりないのかもしれない。こういう考え方の違いがにじみ出てる気がする。


[40] 
[[MIME]] の当該規定は、 [[ISO/IEC 8859]] 
規格群が使われている[[欧米]]諸国でも[[英文]]は通じるようにというくらいのニュアンスで作られたものと思われます。

[41] 
その他に[[東アジア]]の各社の独自[[外字]]が追加された[[文字コード]]を使っていても、
標準の[[文字]]だけなら標準の[[文字コード]]を名乗るべきだとする仕様上の根拠としても使えるものです。

[42] 
ところが現実には[[欧米]]でも[[東アジア]]でも、市場で優位な[[外字]]を使った[[文字コード]]が標準の
[[IANA charset]] を名乗るという現象が起こりました。

[EG[

[43] 例えば [CODE[ISO-8859-1]] は [[windows-1252]] の意味で使われ、
[CODE[Shift_JIS]] は [CODE[windows-31j]] の意味で使われています。

]EG]

[44] 
市場で普及した実装には[[文字コードの識別子]]を厳密に使い分けるという意識がなく、
市場で広まっている識別子で当該[[文字コード]]に近いものを選べば概ね正しく解釈してもらえる
(自社製品なら完全に正しく解釈できるからなおよし) というくらいの気持ちだったのでしょう。

;; [45] 厳密に判断する実装は実装コストと処理速度に響きますし、
市場の他の実装で未対応の[[文字コード]]として完全に開けなくなるリスクより、
一部[[文字化け]]したとしてもおおむね読み取れるメリットの方が大きいと考えたのでしょう。

[46] 
本来なら [[IETF]] がこうした傾向が見えた時点で何らかの技術的対応を行うべきだったのでしょうが、
[[IETF]] は完全無視して放置したため、混乱が続き、たまたま選んだ製品の違いによって他の製品の[[利用者]]を攻撃するような人も出てくるような始末でした。
[SEE[ [[IANA charset]] ]]

** 文字コードの判定における選定

[47] 
[[文字コードの判定]]の処理では、判定結果を返すために何らかの既知の[[文字コード]]を選ぶ必要があります。

[48] 
判定対象の[[バイト列]]によっては、該当する[[文字コード]]がいくつも存在することがあります。
(ここで問題とするのは、候補を絞り込めないときではなく、
[[バイト列]]がそれらの共通部分しか使っていないときです。)

[49] 
判定器には3つの選択肢があります。

- [51] どれも等しく候補なのですから、すべてを[[リスト]]として返します。
- [50] [[文字コードの判定]]の結果は[[復号]]に使われます。[[復号]]はどの[[文字コード]]を使っても同じ結果になるのですから、
どれを判定結果として返すかは成り行きで構いません。
- [52] [[復号]]にとってはどれも同じでも、それ以外の用途で結果が変わってくることがありますから、
できるだけ適した[[文字コード]]を選びます。

[53] 
>>52 は、例えば [[HTMLにおける文字コード]]の判定の場合、結果は[[文書の[F[文字符号化]]]]として参照可能になります。
[CODE[document.charset]] でアクセス可能ですし、
[[フォームの提出]]があればその[[文字コード]]で[[フォームデータ]]が送出されます。

[54] 
>>53 に対しては反論もあるでしょう。もしそのような処理にとって重要なら、
[[文字コードの指定]]が省略されているはずがありません。
それがなく判定器の推定に頼らざるを得ないという時点で、そうした処理が入っていないか、
あっても長らく機能しない状態で放置されているに違いありません。
従って、わざわざ苦労してどれかを選ぶ必要はありません。

[56] 
見落とされがちで >>53 で意外と重要なのは、[[文字コード]]に依存した[[フォントの選択]]かもしれません。
明示的な[[言語情報]]が存在しない場合、[[文字コード]]によって[[フォント]]が変わって表示される場合があります。
[SEE[ [[フォントの選択]] ]]

[EG[

[57] 
同じような[[英文]]でも
[CODE[ISO-8859-1]] で[[欧文]]フォントで表示されるか、
[CODE[Shift_JIS]] で[[和文]]フォントで表示されるかで意外と雰囲気がかわります。

[58] 
[[メール]]を読み進めると記事ごとに意味もなく[[フォント]]が変わる、
というのは読者にとってあまり快適ではない体験です。

]EG]


[55] 
>>52 を実装するとしたら、例えば[[ロケール等による文字コード判定の補助]]のような手法が適用できそうです。
[SEE[ [[文字コードの判定]] ]]

* 文脈

[SEE[ [[文字コードの指定]], [[文字コードの判定]] ]]

* 関連

[SEE[ [[文字コードの変換]] ]]

* メモ

[29] 
[CITE@en-US[GNU gettext - Bugs: bug #50357, xgettext doesn't recognise... '''['''Savannah''']''']]
([[Copyright 2016 Free Software Foundation, Inc. Verbatim copying and distribution of this entire article is permitted in any medium, provided this notice is preserved.]]著, [TIME[2017-02-22 15:05:12 +09:00]])
<https://savannah.gnu.org/bugs/?50357>