<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Java

    BlogJava 首頁 新隨筆 聯系 聚合 管理
      8 Posts :: 0 Stories :: 1 Comments :: 0 Trackbacks

    字符集簡史

    在所有字符集中,最知名可能 要數被稱為ASCII的7位字符集了。它是美國信息交換標準委員會 (American?Standards?Committee?for?Information?Interchange)的縮寫,?為美國英語通信所設 計。它由128個字符組成,包括大小寫字母、數字0-9、標點符號、非打印字符(換行符、制表符等4個)以及控制字符(退格、響鈴等)組成。

    但 是,由于他是針對英語設計的,當處理帶有音調標號(形如漢語的拼音)的歐洲文字時就會出現問題。因此,創建出了一些包括255個字符的由ASCII擴展的 字符集。其中有一種通常被成為IBM字符集,它把值為128-255之間的字符用于畫圖和畫線,以及一些特殊的歐洲字符。另一種8位字符集是 ISO?8859-1?Latin?1,也簡稱為ISO?Latin-1。它把位于128-255之間的字符用于拉丁字母表中特殊語言字符的編碼,也因此 而得名。

    歐洲語言不是地球上的唯一語言,因此亞洲和非洲語言并不能被8位字符 集所支持。僅漢語(或pictograms)字母表就有80000以上個字符。但是把漢語、日語和越南語的一些相似的字符結合起來,在不同的語言里,使不 同的字符代表不同的字,這樣只用2個字節就可以編碼地球上幾乎所有地區的文字。因此,創建了UNICODE編碼。它通過增加一個高字節對 ISO?Latin-1字符集進行擴展,當這些高字節位為0時,低字節就是ISO?Latin-1字符。UNICODE支持歐洲、非洲、中東、亞洲(包括 統一標準的東亞像形漢字和韓國像形文字)。但是,UNICODE并沒有提供對諸如Braille,?Cherokee,?Ethiopic, ?Khmer,?Mongolian,?Hmong,?Tai?Lu,?Tai?Mau文字的支持。同時它也不支持如Ahom,?Akkadian, ?Aramaic,?Babylonian?Cuneiform,?Balti,?Brahmi,?Etruscan,?Hittite,?Javanese, ?Numidian,?Old?Persian?Cuneiform,?Syrian之類的古老的文字。

    事 實證明,對可以用ASCII表示的字符使用UNICODE并不高效,因為UNICODE比ASCII占用大一倍的空間,而對ASCII來說高字節的0對他 毫無用處。為了解決這個問題,就出現了一些中間格式的字符集,他們被稱為通用轉換格式,既UTF (Universal?Transformation?Format)。目前存在的UTF格式有:UTF-7,?UTF-7.5,?UTF-8,?UTF -16,?以及?UTF-32。本文討論UTF-8字符集的基礎。

    UTF_8字符集

    UTF -8是UNICODE的一種變長字符編碼,由Ken?Thompson于1992年創建。現在已經標準化為RFC?3629。UTF-8用1到6個字節編 碼UNICODE字符。如果UNICODE字符由2個字節表示,則編碼成UTF-8很可能需要3個字節,而如果UNICODE字符由4個字節表示,則編碼 成UTF-8可能需要6個字節。用4個或6個字節去編碼一個UNICODE字符可能太多了,但很少會遇到那樣的UNICODE字符。

    UFT-8轉換表表示如下:

    UNICODE?UTF-8?
    00000000?-?0000007F?0xxxxxxx?
    00000080?-?000007FF?110xxxxx?10xxxxxx?
    00000800?-?0000FFFF?1110xxxx?10xxxxxx?10xxxxxx?
    00010000?-?001FFFFF?11110xxx?10xxxxxx?10xxxxxx?10xxxxxx?
    00200000?-?03FFFFFF?111110xx?10xxxxxx?10xxxxxx?10xxxxxx?10xxxxxx?
    04000000?-?7FFFFFFF?1111110x?10xxxxxx?10xxxxxx?10xxxxxx?10xxxxxx?10xxxxxx?

    實 際表示ASCII字符的UNICODE字符,將會編碼成1個字節,并且UTF-8表示與ASCII字符表示是一樣的。所有其他的UNCODE字符轉化成 UTF-8將需要至少2個字節。每個字節由一個換碼序列開始。第一個字節由唯一的換碼序列,由n位1加一位0組成。n位1表示字符編碼所需的字節數。

    示例

    UNICODE?uCA(11001010)?編碼成UTF-8將需要2個字節:

    uCA?->?C3?8A

    1100?1010
    110xxxxx?10xxxxxx

    1100?1010?->?110xxxxx?10xxxxxx
    ->?110xxxxx?10xxxxx0
    ->?110xxxxx?10xxxx10
    ->?110xxxxx?10xxx010
    ->?110xxxxx?10xx1010
    ->?110xxxxx?10x01010
    ->?110xxxxx?10001010
    ->?110xxxx1?10001010
    ->?110xxx11?10001010
    ->?11000011?10001010
    ->?C3?8A

    UNICODE?uF03F?(11110000?00111111)?編碼成UTF-8將需要3個字節:

    u?F03F?->?EF?80?BF

    1111?0000?0011?1111?->?1110xxxx?10xxxxxx?10xxxxxx
    ->?11101111?10000000?10111111
    ->?EF?80?BF

    譯者注:由上分析可以看到,UNCODE到UTF-8的轉換就是先確定編碼所需要的字節數,然后用UNICODE編碼位從低位到高位依次填入上面表示為x的位上,不足的高位以0補充。以上是個人經驗,如有錯誤,請不惜指教,謝過先:)

    UTF-8編碼的優點:

    UTF-8編碼可以通過屏蔽位和移位操作快速讀寫。
    字符串比較時strcmp()和wcscmp()的返回結果相同,因此使排序變得更加容易。
    字節FF和FE在UTF-8編碼中永遠不會出現,因此他們可以用來表明UTF-16或UTF-32文本(見BOM)
    UTF-8?是字節順序無關的。它的字節順序在所有系統中都是一樣的,因此它實際上并不需要BOM。

    UTF-8編碼的缺點:

    你無法從UNICODE字符數判斷出UTF-8文本的字節數,因為UTF-8是一種變長編碼
    它需要用2個字節編碼那些用擴展ASCII字符集只需1個字節的字符
    ISO?Latin-1?是UNICODE的子集,但不是UTF-8的子集
    8位字符的UTF-8編碼會被email網關過濾,因為internet信息最初設計為7為ASCII碼。因此產生了UTF-7編碼。
    UTF-8?在它的表示中使用值100xxxxx的幾率超過50%,?而現存的實現如ISO?2022,?4873,?6429,?和8859系統,會把它錯認為是C1?控制碼。因此產生了UTF-7.5編碼。

    修正的UTF-8:


    java使用UTF-16表示內部文本,并支持用于字符串串行化的非標準的修正UTF-8編碼。標準UTF-8和修正的UTF-8有兩點不同:
    修 正的UTF-8中,null字符編碼成2個字節(11000000?00000000)?而不是標準的1個字節(00000000),這樣作可以保證編碼 后的字符串中不會嵌入null字符。因此如果在類C語言中處理字符串,文本不會在第一個null字符時截斷(C字符串以null結尾)。
    在標準 UTF-8編碼中,超出基本多語言范圍(BMP?-?Basic?Multilingual?Plain)的字符被編碼為4字節格式,但是在修正的UTF -8編碼中,他們由代理編碼對(surrogate?pairs)表示,然后這些代理編碼對在序列中分別重新編碼。結果標準UTF-8編碼中需要4個字節 的字符,在修正后的UTF-8編碼中將需要6個字節。

    位序標志BOM


    BOM(Byte?Order?Mark)是一個字符,它表明UNICODE文本的UTF-16,UTF-32的編碼字節順序(高字節低字節順序)和編碼方式(UTF-8,UTF-16,UTF-32,?其中UTF-8編碼是字節順序無關的)。

    如下所示:

    Encoding?Representation?
    UTF-8?EF?BB?BF?
    UTF-16?Big?Endian?FE?FF?
    UTF-16?Little?Endian?FF?FE?
    UTF-32?Big?Endian?00?00?FE?FF
    UTF-32?Little?Endian?FF?FE?00?00

    UTF-8?C++?程序編碼示例:

    下面是四個C++函數,他們分別實現2字節和4字節UNICODE和UTF-8之間的轉換。

    #define?MASKBITS?0x3F
    #define?MASKBYTE?0x80
    #define?MASK2BYTES?0xC0
    #define?MASK3BYTES?0xE0
    #define?MASK4BYTES?0xF0
    #define?MASK5BYTES?0xF8
    #define?MASK6BYTES?0xFC

    typedef?unsigned?short?Unicode2Bytes;
    typedef?unsigned?int?Unicode4Bytes;

    void?UTF8Encode2BytesUnicode(std::vector<?Unicode2Bytes?>?input,
    std::vector<?byte?>&?output)
    {
    for(int?i=0;?i?<?input.size();?i++)
    {
    //?0xxxxxxx
    if(input?<?0x80)
    {
    output.push_back((byte)input);
    }
    //?110xxxxx?10xxxxxx
    else?if(input?<?0x800)
    {
    output.push_back((byte)(MASK2BYTES?|?input?>>?6));
    output.push_back((byte)(MASKBYTE?|?input?&?MASKBITS));
    }
    //?1110xxxx?10xxxxxx?10xxxxxx
    else?if(input?<?0x10000)
    {
    output.push_back((byte)(MASK3BYTES?|?input?>>?12));
    output.push_back((byte)(MASKBYTE?|?input?>>?6?&?MASKBITS));
    output.push_back((byte)(MASKBYTE?|?input?&?MASKBITS));
    }
    }
    }

    void?UTF8Decode2BytesUnicode(std::vector<?byte?>?input,
    std::vector<?Unicode2Bytes?>&?output)
    {
    for(int?i=0;?i?<?input.size();)
    {
    Unicode2Bytes?ch;

    //?1110xxxx?10xxxxxx?10xxxxxx
    if((input?&?MASK3BYTES)?==?MASK3BYTES)
    {
    ch?=?((input?&?0x0F)?<<?12)?|?(
    (input[i+1]?&?MASKBITS)?<<?6)
    |?(input[i+2]?&?MASKBITS);
    i?+=?3;
    }
    //?110xxxxx?10xxxxxx
    else?if((input?&?MASK2BYTES)?==?MASK2BYTES)
    {
    ch?=?((input?&?0x1F)?<<?6)?|?(input[i+1]?&?MASKBITS);
    i?+=?2;
    }
    //?0xxxxxxx
    else?if(input?<?MASKBYTE)
    {
    ch?=?input;
    i?+=?1;
    }

    output.push_back(ch);
    }
    }

    void?UTF8Encode4BytesUnicode(std::vector<?Unicode4Bytes?>?input,
    std::vector<?byte?>&?output)
    {
    for(int?i=0;?i?<?input.size();?i++)
    {
    //?0xxxxxxx
    if(input?<?0x80)
    {
    output.push_back((byte)input);
    }
    //?110xxxxx?10xxxxxx
    else?if(input?<?0x800)
    {
    output.push_back((byte)(MASK2BYTES?|?input?>?6));
    output.push_back((byte)(MASKBYTE?|?input?&?MASKBITS));
    }
    //?1110xxxx?10xxxxxx?10xxxxxx
    else?if(input?<?0x10000)
    {
    output.push_back((byte)(MASK3BYTES?|?input?>>?12));
    output.push_back((byte)(MASKBYTE?|?input?>>?6?&?MASKBITS));
    output.push_back((byte)(MASKBYTE?|?input?&?MASKBITS));
    }
    //?11110xxx?10xxxxxx?10xxxxxx?10xxxxxx
    else?if(input?<?0x200000)
    {
    output.push_back((byte)(MASK4BYTES?|?input?>>?18));
    output.push_back((byte)(MASKBYTE?|?input?>>?12?&?MASKBITS));
    output.push_back((byte)(MASKBYTE?|?input?>>?6?&?MASKBITS));
    output.push_back((byte)(MASKBYTE?|?input?&?MASKBITS));
    }
    //?111110xx?10xxxxxx?10xxxxxx?10xxxxxx?10xxxxxx
    else?if(input?<?0x4000000)
    {
    output.push_back((byte)(MASK5BYTES?|?input?>>?24));
    output.push_back((byte)(MASKBYTE?|?input?>>?18?&?MASKBITS));
    output.push_back((byte)(MASKBYTE?|?input?>>?12?&?MASKBITS));
    output.push_back((byte)(MASKBYTE?|?input?>>?6?&?MASKBITS));
    output.push_back((byte)(MASKBYTE?|?input?&?MASKBITS));
    }
    //?1111110x?10xxxxxx?10xxxxxx?10xxxxxx?10xxxxxx?10xxxxxx
    else?if(input?<?0x8000000)
    {
    output.push_back((byte)(MASK6BYTES?|?input?>>?30));
    output.push_back((byte)(MASKBYTE?|?input?>>?18?&?MASKBITS));
    output.push_back((byte)(MASKBYTE?|?input?>>?12?&?MASKBITS));
    output.push_back((byte)(MASKBYTE?|?input?>>?6?&?MASKBITS));
    output.push_back((byte)(MASKBYTE?|?input?&?MASKBITS));
    }
    }
    }

    void?UTF8Decode4BytesUnicode(std::vector<?byte?>?input,
    std::vector<?Unicode4Bytes?>&?output)
    {
    for(int?i=0;?i?<?input.size();)
    {
    Unicode4Bytes?ch;

    //?1111110x?10xxxxxx?10xxxxxx?10xxxxxx?10xxxxxx?10xxxxxx
    if((input?&?MASK6BYTES)?==?MASK6BYTES)
    {
    ch?=?((input?&?0x01)?<<?30)?|?((input[i+1]?&?MASKBITS)?<<?24)
    |?((input[i+2]?&?MASKBITS)?<<?18)?|?((input[i+3]
    &?MASKBITS)?<<?12)
    |?((input[i+4]?&?MASKBITS)?<<?6)?|?(input[i+5]?&?MASKBITS);
    i?+=?6;
    }
    //?111110xx?10xxxxxx?10xxxxxx?10xxxxxx?10xxxxxx
    else?if((input?&?MASK5BYTES)?==?MASK5BYTES)
    {
    ch?=?((input?&?0x03)?<<?24)?|?((input[i+1]
    &?MASKBITS)?<<?18)
    |?((input[i+2]?&?MASKBITS)?<<?12)?|?((input[i+3]
    &?MASKBITS)?<<?6)
    |?(input[i+4]?&?MASKBITS);
    i?+=?5;
    }
    //?11110xxx?10xxxxxx?10xxxxxx?10xxxxxx
    else?if((input?&?MASK4BYTES)?==?MASK4BYTES)
    {
    ch?=?((input?&?0x07)?<<?18)?|?((input[i+1]
    &?MASKBITS)?<<?12)
    |?((input[i+2]?&?MASKBITS)?<<?6)?|?(input[i+3]?&?MASKBITS);
    i?+=?4;
    }
    //?1110xxxx?10xxxxxx?10xxxxxx
    else?if((input?&?MASK3BYTES)?==?MASK3BYTES)
    {
    ch?=?((input?&?0x0F)?<<?12)?|?((input[i+1]?&?MASKBITS)?<<?6)
    |?(input[i+2]?&?MASKBITS);
    i?+=?3;
    }
    //?110xxxxx?10xxxxxx
    else?if((input?&?MASK2BYTES)?==?MASK2BYTES)
    {
    ch?=?((input?&?0x1F)?<<?6)?|?(input[i+1]?&?MASKBITS);
    i?+=?2;
    }
    //?0xxxxxxx
    else?if(input?<?MASKBYTE)
    {
    ch?=?input;
    i?+=?1;
    }
    output.push_back(ch);
    }
    }


    限譯者水平有限,有不解之處請參考原文。版權屬原文作者所有,轉載請注明出處及作者。

    原文參見:http://www.codeguru.com/Cpp/misc ... article.php/c10451/

    posted on 2006-06-29 16:00 java執著者 閱讀(2236) 評論(0)  編輯  收藏

    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 亚洲高清无在码在线电影不卡| 亚洲国产香蕉人人爽成AV片久久| 亚洲国产精品无码一线岛国| a毛片成人免费全部播放| 国产免费69成人精品视频| 亚洲av永久无码天堂网| 午夜神器成在线人成在线人免费| 亚洲一区二区三区成人网站| 天天拍拍天天爽免费视频| 亚洲一线产区二线产区区| 国产精品深夜福利免费观看 | 亚洲国产成人精品无码区二本 | 亚洲综合在线另类色区奇米| xxxxxx日本处大片免费看| 色噜噜亚洲精品中文字幕| 两个人日本WWW免费版| 亚洲av永久无码精品国产精品| 日韩电影免费在线观看| 亚洲日韩国产精品无码av| 国产成人A在线观看视频免费| 亚洲国产成人AV在线播放| 亚洲女人被黑人巨大进入| 久久99精品免费一区二区| 国产亚洲国产bv网站在线| 麻豆最新国产剧情AV原创免费 | 日韩亚洲国产高清免费视频| 日韩成人免费在线| 免费激情网站国产高清第一页| 亚洲精品国产美女久久久| 国产精品免费观看| 久久亚洲中文无码咪咪爱| 亚洲色精品aⅴ一区区三区| 99re在线免费视频| 久久亚洲精品无码网站| 亚洲va无码va在线va天堂| 女人18毛片免费观看| 中文在线观看永久免费 | 亚洲色成人网站WWW永久四虎| 亚洲免费日韩无码系列| 91九色老熟女免费资源站| 一级毛片免费不卡|