UnicodeとUTF-8間の変換


ここ数日の研究を通して、UnicodeとUTF-8の符号化の違いがやっと分かった.Unicodeは1つの文字セットであり、UTF-8はUnicodeの1つであり、Unicodeは定長で2バイトであり、UTF-8は可変であり、漢字にとってUnicodeが占有するバイトはUTF-8が占有するバイトより1バイト少ない.Unicodeは2バイト、UTF-8は漢字が3バイトです.
注意:Unicode符号化現在計画されている総空間は17個の平面で、0 x 0000から0 x 10 FFFFFFです.各平面には65536個の符号点がある.そのため、この総長さも100万個以上ある.
UTF-8符号化文字は理論的には最大6バイトまで可能であるが、16ビットBMP(Basic Multilingual Plane)文字は最大3バイトまでしか使用できない.UTF-8コード表を見てみましょう.
 U-00000000 - U-0000007F: 0xxxxxxx
        U-00000080 - U-000007FF: 110xxxxx 10xxxxxx
        U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
        U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
        U-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
        U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

xxxの位置は文字符号化数のバイナリで表されるビットで埋め込まれ、右側のxほど特殊な意味が少なく、最短の文字符号化数を表すのに十分なマルチバイト列しかありません.なお、マルチバイト列では、最初のバイトの先頭「1」の数が、列全体のバイト数である.一方,1行目は0で始まるが,ASCII符号化に対応するため1バイト,2行目は2バイト文字列,3行目は漢字のように3バイトである,ということである.(個人的には、前の1の個数をバイト数と簡単に見ることができると思います)
UnicodeをUTF-8に変換するには、彼らの違いがどこにあるのかを知る必要があります.次にUnicodeでの符号化はどのようにUTF-8に変換されるのかを見てみましょう.UTF-8では、1文字のバイトが0 x 80(128)未満であればASCII文字で、1バイトを占めています.UTF-8はASCII符号化に互換性があるため、変換しなくてもいいです.Unicodeで漢字「あなた」の符号化が「u 4 F 60」であれば、それをバイナリ100111101100000に変換し、UTF-8の方法で変換します.Unicodeバイナリは地位から上位にバイナリ数字を取り出すことができ、毎回6ビットを取ることができ、上記のようなバイナリはそれぞれ以下のようなフォーマットに取り出すことができ、前面はフォーマットで埋め、8ビット未満は0で埋めることができる.
unicode: 100111101100000                  4F60
utf-8:    11100100,10111101,10100000       E4BDA0

上からUnicodeからUTF-8への変換が直感的にわかりますが、もちろんUTF-8のフォーマットを知っていれば逆演算が可能になります.フォーマットに従ってバイナリの対応する位置から取り出し、変換すると得られるUnicode文字になります(この演算は「シフト」でできます).上記の「あなた」の変換のように、その値が0 x 800よりも0 x 10000よりも大きいため、3バイト記憶と判断されると、最上位は「12」ビットを右にシフトし、3バイトフォーマットの最上位が11100000(0 xE 0)であるか(|)で求めると最上位の値が得られる.同理2位は「6」位を右にシフトすると最上位と2位のバイナリ値が残り、111111(0 x 3 F)と位置(&)操作を求め、11000000(0 x 80)と加算(|)することができる.3位はシフトせず、最後の6位(111111(ox 3 F)と&)を直接取り、11000000(0 x 80)と加算します(|).OK、変換成功!VC++におけるコードは以下の通りである(UnicodeからUTF-8への変換).
1 const wchar_t pUnicode = L" ";
        2 char utf8[3+1];
        3 memset(utf8,0,4);
        4 utf8[0] = 0xE0|(pUnicode>>12);
        5 utf8[1] = 0x80|((pUnicode>>6)&0x3F);
        6 utf8[2] = 0x80|(pUnicode&0x3F);
        7 utf8[3] = "\0";
        8 //char[4] UTF-8 “ ” 。

もちろんUTF-8からUnicodeへの変換もシフトなどで行われ、UTF-8のフォーマットに対応する位置のバイナリ数を絞り出すことになる.上記の例では「あなた」は3バイトであるため、各バイトを処理し、上位から下位まで処理する.UTF-8では「あなた」は111001001110110100000です.高位から最初のバイト11100100はその中の「0100」を取り出すことであり、これは11111(0 x 1 F)と(&)を取るだけで、3バイトで最も位置が12ビット前にあることがわかります.毎回6ビットを取るからです.その結果、12位を左にシフトし、最高位はこのように0100000000000ドルを達成した.2位は「111101」を取り出すため、2バイト目の10111101と111111(0 x 3 F)を(&)に合わせるだけです.得られた結果を6ビット左にシフトし、最高バイトで得られた結果を和(|)すると、2ビット目はこのように完了し、0100111101000000となった.このようにして最後のビットを直接111111(0 x 3 F)と(&)を取り、前に得られた結果と(|)を取ると、結果0100111101100000が得られる.OK、変換成功!VC++におけるコードは以下の通りである(UTF-8からUnicodeへの変換). 
 1 //UTF-8 
    2 const char* utf8 = " ";
    3 wchar_t unicode;
    4 unicode = (utf8[0] & 0x1F) << 12;
    5 unicode |= (utf8[1] & 0x3F) << 6;
    6 unicode |= (utf8[2] & 0x3F);
    7 //unicode is ok!

もちろんプログラミングの過程で1つの文字だけを変換することはできません.ここで注意しなければならないのは、文字の長さをはっきり計算しなければなりません.そうしないと...以上、私がここ数日検討した結果、Unicodeの変換GB 2312については、MFCにWindowsに付属のAPI(WideCharToMultiByte)が変換可能である.これによりUTF-8形式をGB 2312に変換することができ、ここでは後述しないが、より良い方法があれば教えてほしい.