`
fandayrockworld
  • 浏览: 312971 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

正确理解UNICODE UTF-8等编码方式

阅读更多

转载出处:http://blog.csdn.net/polarman/archive/2007/04/30/1593159.aspx

如果你开发过的软件项目中涉及到多语言支持的问题,那么相信你没少碰到过乱码问题,然后在寻求解决问题的途径过程中被一些概念如ASCII, ISO-8859-1, Unicode,UTF-8,GBK,GB2312等等所困扰。本文有助于你正确的理解这些概念。

1. ASCII

用7位编码将英文字符和一些常用的符号存诸为从0到127的数值。



2. ISO-8859-1

法语、西班牙语和德语之类的西欧语言都使用叫做ISO-8859-1的编码系统(也叫做“latin-1”)。它使用7位ASCII字符表示从0到127的字符,但接着扩展到了128-255的范围来表示如n上带有一个波浪线(241),和u上带有两个点(252)的字符等等。可以说ASCII是ISO-8859-1的子集。



3. Unicode

    Unicode用一个2字节数字表示每个字符,从0到65535。每个 2 字节数字表示至少在一种世界语言中使用的一个唯一字符。(在多种语言中都使用的字符具有相同的数字码。)这样就确保每个字符一个数字,并且每个数字一个字符。Unicode数据永远不会模棱两可。Unicode使用相同的数字表示ASCII和ISO-8859-1中的字符。只是这两种编码用一个字节表示,而Unicode用两个字节表示。所以Unicode表示这两种编码的字符时只要用低字节就可以了,高字节为0。



4. UTF-8

    UTF-8是一种变长的编码方式,每个UTF-8的编码可以是1至6个字节长。它将Unicode编码的字符采用变长的方式进行编码。对Unicode中属于ISO-8859-1的编码采用和ISO-8859-1相同的单字节编码。其他字符采用两字节以上的编码。实际上对于两个字节的Unicode编码,UTF-8只要三个字节即可表示。第一个字节由n个1(1< n <= 6)开始, n表示编码的字节数,后面每个字节都以10开始,后面6位为有效位。将第一位的剩余位和后面的所有字节的后六位连接起来就是对应的Unicode编码的数值。例如汉字“中”的编码:



Unicode:           4E      2D

01001110 00101101



UTF-8:              E4      B8     AD

11100100 10111000 10101101



可以通过以下方式进行证实:

       用记事本创建一个文本文件,输入汉字“中”分别保存为Unicode格式和UTF-8格式。 将UltraEdit的自动识别UTF-8文件格式选项禁止,然后用其打开这两个文件,选用二进制查看方式,可以看到:


    UTF-8格式文件编码为“EF BB BF E4 B8 AD”。其中有个三字节的前缀“EF BB BF”,这是UTF-8格式文本文件的标识。不过这个前缀不要,某些文本查看软件也可以通过编码判断出UTF-8格式。“E4 B8 AD”就是“中”的UTF-8编码。


    Unicode格式的文件的完整编码是“FF FE 2D 4E”。前面有个双字节前缀“FF FE”,这是Unicode格式文本文档的编码标识。而我们看到的编码是“2D 4E”,而不是如我前面所说的“4E 2D”,为什么呢?因为数字是按照低字节在先高字节在后的顺序存储的,所以实际的Unicode编码恰恰是“4E2D”。



5. GB2312和GBK

       这两种编码都是汉字的编码标准,其中前者是后者的子集。GBK编码的文本文档中对于ASCII中的字符用相同的单字节表示;对于汉字和汉语中的标点符号等采用双字节编码,其中高字节大于0x80,而ASCII的所有字符的编码均小于0x80, 所以ASCII和GBK的字符是可以混和起来的。GBK的字符集和Unicode进行转换是无规则的,需要转换表才能进行转换。



6.下面给出我用Java语言写的Unicode和UTF-8转换的程序片段,供大家参考。



因为Java语言的字符使用Unicode编码的,所以程序中是对UTF-8编码的字符串的字节数组和Java的String类型进行转换。String对象中的每一个Character就是一个Unicode编码的字符。

public String utf8Bytes2String(byte[] buff){

              if(buff == null)

                     return null;

              

              StringBuffer sb = new StringBuffer();

              

              int idx = 0;

              

              if(buff[0] == (byte)0xEF &&

                            buff[1] == (byte)0xBB &&

                            buff[2] == (byte)0xBF)

                     idx = 3;//Skip UTF8 header

 

              while(idx < buff.length){

                     int hB = buff[idx] & 0xFF;

                     int bCnt = 0;

                     int check = 0x80;

                     for(int i=0; i<8; i++){

                            if((hB & check) != 0){

                                   bCnt ++;

                                   check >>= 1;

                            }else

                                   break;

                     }

                     

                     if(bCnt <= 1){

                            char c = 0;

                            c |= buff[idx] & 0xFF;

                            sb.append(c);

                            idx++;

                     }else if(bCnt == 2){

                            char c = 0;

                            c |= buff[idx] & 0x03;

                            c <<= 6;

                            if((buff[idx+1] & 0xC0) != 0x80)

                                   return null;

                            c |= buff[idx+1] & 0x3F;

                            idx += 2;

                            sb.append(c);

                     }else if(bCnt == 3){

                            char c = 0;

                            c |= buff[idx] & 0x0F;

                            c <<= 6;

                            if((buff[idx+1] & 0xC0) != 0x80)

                                   return null;

                            c |= buff[idx+1] & 0x3F;

                            c <<= 6;

                            if((buff[idx+2] & 0xC0) != 0x80)

                                   return null;

                            c |= buff[idx+2] & 0x3F;

                            idx += 3;

                            sb.append(c);

                     }else

                            return null;

              }

              

              return sb.toString();

       }

       

       public byte[] string2Utf8Bytes(String str){

              if(str == null)

                     return null;

              

              ByteArrayOutputStream bos = new ByteArrayOutputStream();

              try {

                     string2Utf8Stream(str, bos);

              } catch (IOException e) {

                     e.printStackTrace();

              }

              return bos.toByteArray();

       }

 

public void string2Utf8Stream(String str, OutputStream os) throws IOException {

              if(str == null || os == null)

                     return;

              

              for(int i=0; i<str.length(); i++){

                     char c = str.charAt(i);

                     if(c < 0x80){

                            os.write((byte)c);

                     }else if(c >=0x80 && c < 0x100){

                            int hi = c >> 6;

                            hi |= 0xC0;

                            int lo = c & 0x3F;

                            lo |= 0x80;

                            os.write(hi);

                            os.write(lo);

                     }else{

                            int first = c >> 12;

                            first |= 0xE0;

                            int second = c >> 6;

                            second &= 0x3F;

                            second |= 0x80;

                            int third = c & 0x3F;

                            third |= 0x80;

                            os.write(first);

                            os.write(second);

                            os.write(third);

                     }

              }

       }



分享到:
评论

相关推荐

    UNICODE与UTF-8转换

    **二、UTF-8编码** UTF-8是一种变长的Unicode转换格式,它将UNICODE码点转换为可变长度的字节序列。UTF-8的优势在于其对ASCII字符的兼容性:英文和其他使用ASCII字符的语言,如大部分编程语言,只需要1个字节表示,...

    字符编码转换类,支持 ANSI、Unicode、Unicode big endian、UTF-8、UTF-8+Bom互相转换

    对于ASCII字符,UTF-8编码与ASCII相同,都是单字节。UTF-8的特殊之处在于它包含一个字节顺序标记(BOM),即UTF-8+BOM,但大多数情况下,UTF-8无BOM更常见。 在PHP中,进行字符编码转换可以使用内置函数,如`mb_...

    utf-8.rar_c++ string utf-8_string to utf-8_utf_utf 8_utf-8

    在C++编程中,UTF-8编码是一种广泛使用的字符编码标准,它能够表示Unicode字符集中的所有字符。本文将深入探讨如何在C++中处理UTF-8字符串,并介绍相关的关键概念和技术。 首先,C++标准库并没有直接支持UTF-8编码...

    编码查询 各种文本转到 unicode utf-8 gb2312 编码 unicode utf-8 gb2312 编码转换到文字

    Unicode的实现方式之一就是UTF-8编码,这是一种变长编码,可以表示Unicode中的所有字符。UTF-8的特点是对于ASCII字符,它与ASCII编码完全兼容,且随着字符复杂性的增加,编码所占的字节数也相应增加。 GB2312是中国...

    汉字字符编码(utf-8 unicode gb2312)

    - **UTF-8中文字符表.txt**:这个文件可能包含了使用UTF-8编码的所有中文字符,每个字符会以UTF-8编码的形式展示,通常用于验证程序对UTF-8编码的支持或进行字符编码教学。 - **unicode 汉字表.txt**:此文件很可能...

    UTF-8 汉字码表

    ### UTF-8编码详解与汉字码表解析 #### UTF-8编码原理 UTF-8(Unicode Transformation Format - 8 bits)是一种变长字符编码,由Ken Thompson于1992年设计,旨在解决多语言环境下字符编码兼容性问题。其核心优势...

    GB/BIG5/UTF-8 文件编码批量转换程序

    "GB/BIG5/UTF-8 文件编码批量转换程序"就是解决这个问题的工具,它可以将GB2312(GBK)、BIG5编码的文件批量转换为UTF-8编码,确保在各种环境中正确显示文本。 3. **批量转换** 批量转换功能使得用户无需逐个文件...

    Java解决UTF-8的BOM问题

    BOM是Unicode编码中的一个特殊字符,它的Unicode码点是`U+FEFF`,在UTF-8编码中,BOM的字节序列是`EF BB BF`。BOM的主要作用是在数据传输或存储时标识文件或数据流的字符编码,尤其是区分大端序(Big-Endian)和小端...

    JAVA字符编码:Unicode,ISO-8859-1,GBK,UTF-8编码及相互转换

    - **Unicode到UTF-8**: 同样以"a 中文"为例,转换为UTF-8编码后,字节数组为`0x61 0xE4 0xB8 0xAD 0xE6 0x96 0x87`。 - **UTF-8到Unicode**: 反向转换后,结果依然是"a 中文"。 ##### 3. Unicode与ISO-8859-1 - **...

    utf-8码转换器(转换成utf-8码)

    UTF-8编码是一种广泛使用的字符编码标准,它能够表示Unicode字符集中的所有字符。这个“utf-8码转换器”程序是用SWT(Standard Widget Toolkit)开发的,旨在帮助用户将非UTF-8编码的文本转换为UTF-8编码。在IT行业...

    pb12 gb转utf-8

    转换“pb12 gb转utf-8”意味着你可能有一个使用PowerBuilder 12编写的程序或数据库,其中的数据是以GBK编码存储的,现在需要将这些数据转换为UTF-8编码以便在更广泛的环境中使用或与其他系统进行兼容。 这个过程...

    UTF-8编码转化(Visual Basic)

    在Visual Basic编程环境中,处理UTF-8编码的文件或数据时,你需要理解如何读取、写入以及转换UTF-8格式的数据。以下是一些关键的知识点: 1. **Unicode与UTF-8**: Unicode是一个统一的字符集,包含世界上几乎所有...

    ASCII、Unicode和UTF-8编码.docx

    字符编码是计算机处理文本的关键...总结来说,ASCII、Unicode和UTF-8编码分别代表了从基础的英文字符集到全球多语言字符集的演进,并通过UTF-8实现了一种高效且兼容的编码方式,使得现代计算机能够处理各种语言的文本。

    xml.rar_UTF XML_UTF-8编码_utf_utf-8_xml utf-8

    在"xml.rar_UTF XML_UTF-8编码_utf_utf-8_xml utf-8"这个压缩包中,我们主要探讨的是与XML文档相关的编码问题,特别是UTF-8编码。 UTF-8是一种广泛使用的Unicode字符编码方案。它能够表示Unicode标准中的所有字符,...

    UTF-8toGBK_labview编码gbk_LabVIEWUTF-8_utf-8toGbk_源码.zip

    例如,如果你需要从一个使用GBK编码的系统获取数据,而你的程序默认使用UTF-8编码,那么就需要进行这样的转换,以避免乱码问题。反之,如果你的数据需要发送给使用GBK编码的系统,你也需要做相应的转换。 总之,这...

    易语言判断UTF-8字符

    在处理文本数据时,UTF-8编码是非常常见的一种字符编码方式,它能够支持全球大部分语言的文字。在易语言中,有时候我们需要判断一个字符串是否是UTF-8编码的,这就需要用到"IsTextUTF8"这样的函数。 `IsTextUTF8`...

    Unicode-UTF8-0.62.tar_c_linux_strikemvd_unicode_

    《深入理解Unicode与UTF-8...通过学习和理解Unicode以及其UTF-8编码,开发者可以构建能够正确处理多语言文本的软件,从而提升产品的全球适用性。同时,熟悉相关工具和库的使用,也能提高开发效率,降低bug出现的概率。

    UTF-8 编码转换工具

    UTF-8编码转换工具是一种专门用于处理文本编码...总的来说,理解和使用UTF-8编码转换工具对于处理多语言文件和保证数据的正确性至关重要。通过这类工具,用户可以有效地消除编码不一致带来的困扰,确保信息的准确传递。

    简体繁体转换利器gb2312,big5,utf-8各种编码批量互转

    3. UTF-8:是一种变长的Unicode编码,支持世界上几乎所有的字符集,包括简体中文和繁体中文。UTF-8在互联网上非常普遍,因为它对英文字符效率高且兼容性强。 这个工具能够实现gb2312、big5和utf-8之间的批量转换,...

    日历脚本—utf-8编码

    相比之下,UTF-8编码则是一种变长的Unicode编码方式,它可以表示Unicode字符集中所有的字符。UTF-8的一个显著特点是其对英文字符的处理非常高效,只占用1个字节,而对于中文等多字节字符,它最多可以使用4个字节。这...

Global site tag (gtag.js) - Google Analytics