プロが教える店舗&オフィスのセキュリティ対策術

UTF-8とASCIIはそのASCIIコードの範囲のおいて
互換性を持ちます。(と、書籍や多種な文献にはそういった記述があります)

たとえば【A】という文字をUTF-8で符号化した際は【41】(16進数で)
さらにASCIIコードでも【41】という値がAという文字に割り当てられています。
確かに、一件互換しているようにみえますが、UTF-8っていうことは最終的には
Unicode上のコードポイントの値・・・つまり0x0041という値に復元?(というのでしょうか)するわけですよね?
でそのUnicodeの文字集合上から復元したコードポイントに対応する文字を参照しAという文字をみつけてくると・・・。
これって【A】という文字をUTF-8で符号化した歳のバイト列はASCIIと一致しているけれど
結局Unicodeコードポイントに直した場合【00】という上位バイトが無駄にくっついてきて【0x0041】となり
互換性がなくなるのではとおもったのですが・・・。

これはどういう意味の互換性なのでしょうか?
識者の方ご教授ください。
お願い致します。

A 回答 (9件)

No1,3,6です。



>とあった時、おそらくどの言語でもそうだと思うのですが、スクリプトファイル内の特定の文字列はそれぞれ個別にエンコーディング情報を持つと思います。(※言語によっては持たいない?)

持たないのが普通です。
文字列個別にエンコード情報を持つのは、メジャーな言語だとRubyくらい?
他の言語では、プログラム中では1つのプログラム中では一種類のエンコードしか扱えません。もしくは、言語は全くエンコードを関知せず、すべてプログラマが管理するか。

最初の疑問に戻って、
「UTF-8とASCIIはそのASCIIコードの範囲において互換性を持ちます。」
というのは、
「ASCIIコードの範囲の文字を、ASCIIでエンコードしても、UTF-8でエンコードしても、全く同じ値になる」という意味であり、それ以上でも以下でも無いです。
別の言い方をすると、ASCIIコードの範囲の文字しか含まれないファイルであれば、そのファイルのエンコードがASCIIだとかUTF-8だとか、さらに(バックすらスラッシュ等)一部の記号を除けばSHIFT_JISだとかeuc-jpだとかいうのも区別できないというか同じです。
    • good
    • 5

元々の疑問である互換性については、このように見てみたら分かりますか?



(A) ASCIIで書かれたテキストファイルを、UTF-8として読み込む場合
テキストファイルの中の'A'(0x41)はUTF-8でも同様に'A'に対応するので、問題は発生しません。
たとえばコンピュータの内部表現としてUTF-16を使っている場合は、ファイルを読み込んだ後に1バイトの0x41→2バイトの0x0041に内部的に変換された上で処理が実行されるでしょう。その際、元のファイルで'A'を表していた文字は内部表現でもやはり'A'を表すものとして処理されます。そういう意味で互換性があります。

(B) UTF-8で書かれたテキストファイルを、ASCIIしか理解しないソフトウェアで読み込む場合
ASCIIに含まれる文字だけがそのテキストファイルに書かれているのであれば、ASCIIしか理解しないソフトウェアで読み込んでも問題は発生せず、互換性があります。
一方、UTF-16で"ABC"と書かれたテキストファイルを同じソフトウェアで読み込んだら、余計な0x00のバイトが入るために"ABC"という文字列だと解釈してもらえず、つまり互換性がありません。
漢字などを含むUTF-8のテキストファイルを同じソフトウェアで読み込んだら当然問題が発生しますが、「ASCIIに含まれないコードを読み込んだらその部分を無視する」という作りになっていれば、最低限ASCIIの範囲で書かれた部分だけは元の内容のとおりに読み込んで処理できます。

この回答への補足

>その際、元のファイルで'A'を表していた文字は内部表現でも
>やはり'A'を表すものとして処理されます。そういう意味で互換性があります。

なるほど、符号化した値がASCIIとUTF-8で同じだから相互変換ができるというだけでなく
ASCIIの0x41 と UTF-16における0x0041も同じAを指すように文字コード上でも定義しているというプログラム的な互換性だけでなく、仕様上の互換性も兼用しているという意ですか。

その点は頭から抜け落ちていました。
なるほど。すこし疑問が氷解しました。

補足日時:2012/12/02 17:08
    • good
    • 0

> (※これが気になってますが、符号化されたバイト列を再度文字集合の文字に


> 戻す場合の表現・いいまわしって復号化というような言い方をするのでしょうか
> ?)

「符号化文字集合」とその元になった「文字集合」は一対一で対応します。
なので,厳密に取り扱う場合を除くと,「符号化文字集合」は「文字集合」と同一視しています。

さて,厳密に取り扱った場合ですが,
「文字集合」の各文字に対して『値を与える』行為を『符号化』と呼んでいます。
なので,「符号化文字集合」の各々の値は,文字そのものを指します。
「符号化文字集合」→「文字集合」の対応付けを辿る行為を表現するなら,
『値に対応付いた文字』
とか
『値にある文字』
とかになると思います。


> このhoge(0x0041)っていう変数をpack()やGetString()などを用いてASCIIコードとして
> Aという文字に復元することはできないけれども、

UTF-16は「エンコーディング」です。
UTF-16という「エンコーディング」をUS-ASCIIという「符号化文字集合」を用いて利用するのであれば,
0x0041はUS-ASCIIの4/1の文字,つまりはAを意味します。


> ASCIIの場合、ASCII文字集合上のコードポイントと符号化した際のバイト値は同一なのですね。

同一です。


> 特定の文字列はそれぞれ個別にエンコーディング情報を持つと思います。(※言語によっては持たいない?)

内部表現としてエンコーディング情報を持つ物はあると思います。
あくまで内部表現であって,文字列の必須情報ではありません。
処理上,その表現が必要だから持っている,というものです。

本質的に,文字はエンコーディング情報を持つ物ではありません。
「あ」は「あ」だし,「A」は「A」です。
あくまで(符号化されていない)「文字集合」に属します。
コンピューターで取り扱うためには番号を振らないといけないので,「符号化文字集合」ができ,
その振られた番号をどう取り扱うかを決めないとコンピューターで使えないので「エンコーディング」ができています。


> UTF-8のアスキー範囲内の文字はUS-ASCIIと同じ符号化を行なっているという

UTF-8自体は,既存のシステムで動作することを念頭に作られたところがあります。
システムの大多数は,少なくともコマンドはUS-ASCIIの範囲で受け付けるため,
そのシステムを障害無く動かせる,という作りになっています。
# EUC-JPなども似た発想があります。あれはISO 2022に則った作りではありますが。
    • good
    • 0

No1,3です。



No3の補足について。

「文字→文字コード」の変換をunpack、その逆をpackと表現しているのであれば、その通りです。

この回答への補足

このひとつ前の回答の内容ですが
>英字の A を、0x41 というコードで表現すると言う意味でUS-ASCIIもUTF-8も同じです。

これはたとえば
CGIの類をUTF-8で書いた時、明確にいうと#coding: utf-8
と明示してスクリプトファイルを書いた時
そのファイル内で変数なりリテラルなりで記述したアスキーコード内の文字に関しては

hoge = "A"

とあった時、おそらくどの言語でもそうだと思うのですが、スクリプトファイル内の
特定の文字列はそれぞれ個別にエンコーディング情報を持つと思います。(※言語によっては持たいない?)

hogeUtf8 = hoge #utf-8という文字コード情報をもつリテラル
hogeAscii = hoge. toAsciiFromUtf8() #メソッドは架空です。

とした場合


hogeUtf8はUTF-8
hogeAsciiはUS-ASCII
と異なる文字コードだけども、
こ両変数は
スクリプトファイルがASCIIでかかれていても、UTF-8でかかれていても
動作する。

これを実現するために
UTF-8のアスキー範囲内の文字はUS-ASCIIと同じ符号化を行なっているという
解釈でおk?

補足日時:2012/12/02 12:17
    • good
    • 0

えーっと,「符号化文字集合」と「エンコーディング」の関係がわかっていないのでしょう。


# 規格によって言葉が色々異なるのですが……。

まず,「文字集合」が存在します。
Unicodeなどの他に,常用漢字表なども「文字集合」です。
数値が振られていないため,コンピューターで取り扱う上では「文字集合」は現実的には使われませんが。

そして,「文字集合」に数値を振った物が「符号化文字集合」です。
Unicode, JIS X 0208やUS-ASCIIは「符号化文字集合」です。
Unicodeのコードポイントとは,この「符号化文字集合」に振られた数値のことになります。
JIS X 0208では区点値です。

「エンコーディング」は「符号化文字集合」をどのようにコンピューター上で取り扱うか,という取り決めです。
UTF-16, UTF-8,Shift_JISやUS-ASCIIは「エンコーディング」です。
US-ASCIIは「符号化文字集合」であり「エンコーディング」でもあります。
で,「符号化文字集合」にISO/IEC 10646-1 (≒Unicode) で,「エンコーディング」はShift_JISということもよくあります。
# HTML 4.01のShift_JIS文書など。HTML 4.01は文字集合がISO/IEC 10646-1と規定されています。

> UTF-8とASCIIはそのASCIIコードの範囲のおいて互換性を持ちます。
というのは,「エンコーディング」の取り決めの話です。
Unicodeが文字集合である場合,U+0000 - U+007Fの範囲はUS-ASCII/UTF-8ともに0x00 - 0x7Fに符号化されます。

この回答への補足

別の方の回答補足にも書いたのですが、

>Unicodeが文字集合である場合,U+0000 - U+007Fの範囲は
>US-ASCII/UTF-8ともに0x00 - 0x7Fに符号化されます。

これは

hoge ="A"とあった場合
UTF-16だった場合 0x0041と符号化されますね?

このhoge(0x0041)っていう変数をpack()やGetString()などを用いてASCIIコードとして
Aという文字に復元
(※これが気になってますが、符号化されたバイト列を再度文字集合の文字に
戻す場合の表現・いいまわしって復号化というような言い方をするのでしょうか
?)
することはできないけれども、

hoge = "A"
これが、UTF-8の場合、
0x41となって
これは
ASCIIコードにおける【A】という文字を符号化した値と同一だから
コンピューター的にはこの0x41がもともとASCIIの文字を符号化したものなのか
それともUTF-8から符号化されたものなのかという点問題ではないということですかね?

※>US-ASCIIは「符号化文字集合」であり「エンコーディング」でもあります。
どうやら見落としていたのはここだったようです。
ASCIIの場合、ASCII文字集合上のコードポイントと符号化した際のバイト値は同一なのですね。

補足日時:2012/12/02 12:32
    • good
    • 0

だからなんで


> というUnicode上の文字集合に復帰させると思います。
こんなことをするの?
UTF-8とASCIIに互換性があるというのは「符号化した結果」の話なのに
符号化する前に話を戻すのはナンセンスです。
    • good
    • 0

No1です。



コードポイントを求めた時点ですでにUTF-8では無くなっていますけど。
英字の A を、0x41 というコードで表現すると言う意味でUS-ASCIIもUTF-8も同じです。

この回答への補足

>英字の A を、0x41 というコードで表現すると言う意味でUS-ASCIIもUTF-8も同じです。
あー・・・。
ひょっとしてこう考えるといいのかな?

0x41(何かしらの方法でAという文字をunpackしたあと)というバイト列を
再度なにかしら言語でpackして任意の文字コードの文字集合上のAに復帰させる場合に
0x41はpackしてAという文字に戻すにしてもASCIIコードとしても復帰させれるし、
UTF-8エンコーディングとしても復帰できるといった感じ。

うーん。
あるいはUTF-8のAをunpackしても0x41が返ってくるし
US-ASCIIで記述したファイルのAでもunpackすると0x41が返ってくる。
こう捉えたほうがいいのでしょうか?

補足日時:2012/12/02 00:49
    • good
    • 0

> 結局Unicodeコードポイントに直した場合【00】という上位バイトが無駄にくっついてきて【0x0041】となり


上位に00をつけた時点でUTF-8じゃないよね。
あなたはUTF-8じゃないものとASCIIコードを比較して互換性がないと言っているだけ。

この回答への補足

>上位に00をつけた時点でUTF-8じゃないよね。

いえ、ですからUTF-8はUnicodeの文字集合上の符号位置をそれぞれ1byteや2byteあるいは3byteのバイト列に符号化することをいいますよね?
この点はお分かりですよね?

で2byteや3byteのマルチバイトに符号化されたバイト列は
Unicode上の符号位置に復帰させないとどのような文字をいみしているかがわからないわけですよね?
そこでRFC等で定義されている計算仕様で例えば【E38182】というバイト列を【3042】
というUnicode上の文字集合に復帰させると思います。

でこれは、1byteで符号化されたバイト列も例外ではないですよね?
とするならば、【41】というバイト列もUnicode上の符号位置へ復帰させるために
Unicode上の符号位置とバイト数をあわせるために【00】を付ける必要があるのでは?
という意味です。

補足日時:2012/12/01 22:33
    • good
    • 0

Aを0x0041で表現するのはUTF-16であり、UTF-8ではありませんので、関係ありません。


ユニコードの A (U+0041) を 0x41 として表現するのがUTF-8です。
ユニコードの A (U+0041) は ASCIIの A (0x41) と同じ文字であると定義されていて、UTF-8ではそれが同じコードで表現されているというのが互換性です。

>UTF-8っていうことは最終的にはUnicode上のコードポイントの値・・・つまり0x0041という値に復元?(というのでしょうか)するわけですよね?

このあたりが意味不明の文になってしまっています。「最終的」とは?
もしかして、画面表示のためにフォントファイルの中からAに相当するフォントデータを探してくるということを言ってますか?それは実装依存でしょうね。

この回答への補足

>ユニコードの A (U+0041) を 0x41 として表現するのがUTF-8です。

Unicodeのコードポイント上にあるU+0041という符号位置をUTF-8の符号化定義に則って
Aという文字は符号化されて0x41というバイト値であらわされているわけですよね?

例えば【あ】という文字の場合Unicode上ではU+3042となっているコードポイントを
UTF-8の符号化規則にのっとって【e38182】という16進数の3byte値になります。
ただこれは、符号化した結果であって、【e38182】=>【U+3042】ともとのUnicode上のコードポイントU+3042を参照する必要があるとおものですが

【A】という文字も【41】=>【U+0041】の位置に復元する必要があるのでは?と思ったのです。

ただ、

>ユニコードの A (U+0041) は ASCIIの A (0x41) と同じ文字であると定義されていて、
>UTF-8ではそれが同じコードで表現されているというのが互換性です。

とありますが?
例えばUTF-8の
UCS-4 範囲 (hex.) UTF-8 8 ビットバイトシーケンス (binary)
0000 0000-0000 007F 0xxxxxxx
0000 0080-0000 07FF 110xxxxx 10xxxxxx
0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx

0001 0000-001F FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
0020 0000-03FF FFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
0400 0000-7FFF FFFF 1111110x 10xxxxxx ... 10xxxxxx

【あ】という日本語はUTF-8という符号化仕様であれば、3行目の
0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
が当てはまります。
これを元にUnicode上のU+3042という符号位置を求める計算をするわけですが・・・。

では、【A】の場合は1行目の
0000 0000-0000 007F 0xxxxxxx
に当てはまります。

UTF-8による符号化の場合で、かつ1byte以下の数値・・・つまり01111111以下の数値の場合は
Unicode上のコードポイントを参照せず、そのままASCIIコードを直接参照するということですか?

もっと言えば、

UTF-8による符号化は0~01111111(0xxxxxxx)の範囲はUS-ASCIIの文字集合参照
それ以降(110xxxxx 10xxxxxx ~)はUTF-8の符号化仕様にのっとって符号化する

という捉え方でよいのでしょうか?

補足日時:2012/12/01 21:00
    • good
    • 1

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!