字符编码(1)——Unicode,utf-8

简介: 字符编码 编码是一个将一组Unicode字符转换业个字节序列的过程。而解码是将一个编码字节序列转换为一组Unicode字符的过程。   Unicode字符是什么? Unicode字符集可以简写为UCS,也就是Unicode charactor set Unicode编码是国际组织制定的可以容纳世界上所有文字和符号的字符编码方案。

字符编码

编码是一个将一组Unicode字符转换业个字节序列的过程。而解码是将一个编码字节序列转换为一组Unicode字符的过程。

 

Unicode字符是什么?

Unicode字符集可以简写为UCS,也就是Unicode charactor set

Unicode编码是国际组织制定的可以容纳世界上所有文字和符号的字符编码方案。它通过00x10FFFF来映射字符,最多可容纳1114112个字符(16进制的10FFFF的值是1114111,然后加一个0x000000就是1114112个)。可以看一下1114112的二进制表示形式为:1 0001 00000000 00000000

 

UTF是什么?

UTFUnicode转换格式的意思,是UCS Transformation Format的缩写。

 

Utf-8

UTF-8以字节为单位对Unicode进行编码。utf-8特点是对不同范围的字符用不同长度的编码。从UnicodeUTF-8的编码方式如下:

Unicode编码(16进制)  UTF-8 字节流(二进制)

000000 - 00007F  0xxxxxxx

000080 - 0007FF  110xxxxx 10xxxxxx

000800 - 00FFFF  1110xxxx 10xxxxxx 10xxxxxx

010000 - 10FFFF  11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

 

例如:这个字的Unicode编码(16进制表示方法)是:8d 75

这个编码在.net中可以通过ToString()方法来实现。为了进行后边的说明。这里先给出测试用的转换方法: 

public   static   class  CharSetHelper
{
    
public   static   string  TransCoding( this   int  iValue,eTrans eType)
    {
        
return  Convert.ToString(iValue, ( int )eType);
    }
    
public   static   string  GetCorrectCoding( this   string  selfChar, Encoding encoding, eTrans eType)
    {
        
int  iUnicode  =  ( int ) char .Parse(selfChar);
        
return  iUnicode.TransCoding(eType);
    }
}

public enum eTrans

{

Binary=2,

Octonary=8,

Decimal=10,

Hexadecimal=16

} 

 

一个枚举,用于枚举数的进制,一个从字串转换到特定的字符编码,并以指定进制表示的方法。

·另外,可以再把系统的计算器调出来,改为科学型。

·准备可以查看进制的编辑器,我用的是ultra

另外说明一下:char.Parse方法:它将指定字符串的值转换为它的等效 Unicode 字符

 

百家姓赵钱孙李中的字,这里是简体赵字。可以查一下它的Unicode编码,并用10进制和16进制表示:

string  cc = " " ;
UnicodeEncoding _unicode 
=   new  UnicodeEncoding();
string  s1  =  cc.GetCorrectCoding(_unicode, eTrans. Decimal);
string  s2  =  cc.GetCorrectCoding(_unicode, eTrans.Hexadecimal);

 

10进制:36213

16进制:8d75

 

然后新建立记事本。写一个字,保存,保存时编码选择unicode。然后用ultra打开。切换到16进制编辑模式。可以看到:FF FE 75 8D

还有一个要说的就是这里的10进制是8D7510进制表示法,同时也是Unicode编码表中汉字的编号。

 

其中8D 75字的16进制编码。而多出来的FE FF就是字节序,byte order markBOM),用来判断字节流的字节序。在传输字节流前,先传输被作为BOM的字符。

下边是utfBOM

UTF-8  EF BB BF

UTF-16LE  FF FE

UTF-16BE  FE FF

UTF-32LE  FF FE 00 00

UTF-32BE  00 00 FE FF

 

这个字节序不要出现在传输中,例如:在进行组包发送数据时,当字符使用utf-8编码时,会多出BOM,所以要先截除BOM,然后进行传输,这点是要注意的。对于utf-8编码的字符,要向前截除3个字节。

 

下面再看一下UTF-8编码的16进制。还是字。在记事本中添加字,编码选择utf-8,然后在ultra中打开,切换到16进制模式,之前,先看一下这个字在程序中的utf-8编码下的16进制情况:

16进制:E8B5B5

现在提供一下编码的16进制查看方法:

public   static   string  GetRightEncodingString( this   string  selfChar,Encoding encoding, eTrans eType)
{
    
byte [] bb  =  encoding.GetBytes(selfChar);
    bb
= bb.Reverse().ToArray();
    
string  strTemp  =   string .Empty; 

    
foreach  ( byte  b1  in  bb)
    {
        strTemp 
+=  Convert.ToInt32(b1.ToString()).TransCoding(eType);
    }

    
return  strTemp;
}

 

这个方法是连着上边的进行的。

utf-8下的的记事本上,字的全16进制格式是:EF BB BF E8 B5 B5

其中后3个字节是字的utf8编码,而前三个字节就是BOM了。

 

再来看一下,utf-8的编码格式:

000000 - 00007F  0xxxxxxx

000080 - 0007FF  110xxxxx 10xxxxxx

000800 - 00FFFF  1110xxxx 10xxxxxx 10xxxxxx

010000 - 10FFFF  11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

07F之间用的一个字节。与Ascii码对应。7F就是10进制的127

1282047之间用2个字节。

204865535之间用3个字节。

655361114111之间用4个字节

 

unicodeutf-8之间的转换怎么样的?还以上表为例子,例如:字,

它的16进制unicode编码是:8D75,它在第三行也就是204865535之间。

000800 - 00FFFF  1110xxxx 10xxxxxx 10xxxxxx

然后,8D75的二进制表示为(用计算器转一下):1000110101110101

然后,用这些二进制从低位向高位(从右向械)依次取6位:

1000110101110101

然后替换x,如果不够位数,则高位用0补,然后得到的二进制是:

111010001011010110110101

然后,这3个字节的16进制就是:E8 B5 B5

 

然后再以字母M来试一下,因为这个字母是Ascii码表中的值(这样说不太准确),或者说它是127之内的值,所以utf-8编码格式与ascii一样。(尽管如此,做为utf-8编码,文本串最前边还是多出3个字节,BOM

 

现在再找一个字:,它的unicode编码值是: 674E

它的范围在:000800 - 00FFFF  1110xxxx 10xxxxxx 10xxxxxx

这个范围内,然后,这2个字节的二进制是:110011101001110,然后由低位向高位按6位取:

110011101001110,不足4位的高位用0补:0110011101001110,然后替换x就是:

11100110100111011000111016进制数是:E69D8E

ultra中可以验证一下:utf-8全文:EF BB BF E6 9D 8E

 

现在通过程序来实现一下Unicodeutf-8的转换(通过移位来进行)

准备工作:参照:1110xxxx 10xxxxxx 10xxxxxx 其中的X0替换,表示为:

11100000 10000000 10000000

然后,一个unicode编码的字符是2个字节,就是16位,而utf-8编码(这里还以汉字为例)是3个字节

UnicodeEncoding _unicoding = new  UnicodeEncoding();
string  str = " " ;
int  k  =   int .Parse(str.GetUnicode( new  UnicodeEncoding(), eTrans.Decimal));
byte [] bb  =  _unicoding.GetBytes(str);

 

先得到字的unicode值和字节。

 

11100000 10000000 10000000

这三个字节,会16进制表示为:0xE00x800x80

这个字的unicode的编码的二进制表示为:1000110101110101

先算第一个字节:

第一个字节为0xE0与上1000(二进制),而1000可以是字的unicode编码右移12位,所以:

int  k1  =  k  >>   12 ;
_list.Add(
0xe0 | k1);

 

第二个字节是0x80与上110101

110101字的unicode编码右移6位,变为:1000110101,然后与上111111就可以了,而11111116进制为:0x3F,所以:

int  k2  =  k  >>   6    & 0x3F ;
_list.Add(
0x80   |  k2);

 

第三个字节是0x80与上110101

110101字的unicode的后6位,所以与上61就可以了,所以:

int  k3  =  k  &   0x3F ;
_list.Add(
0x80   |  k3);

 

结果是:

232181181

E8B5B5

 

博客园大道至简

http://www.cnblogs.com/jams742003/

转载请注明:博客园

目录
相关文章
|
6月前
|
存储 编解码 C语言
ASCII、GBK与UTF-8的联系
ASCII、GBK与UTF-8的联系
87 1
|
5月前
|
存储 自然语言处理 数据可视化
字符集编码(三):Unicode
中国的 GB 编码和日本的 JIS 编码在兼容 ASCII 的同时,又给 ASCII 中的可见字符做了个“全角”编码(原 ASCII 中的字符被称为“半角”字符)。所谓全角和半角字符,在字形和字意上都完全相同,只是全角字符占用宽度(注意不是字形本身的宽度)是半角字符的两倍(据说是为了中英文混排时的美观效果),按照 Unicode 的设计原则,这种问题应该交由文字渲染程序去处理,
53 1
|
存储 网络协议 安全
字符编码技术专题(一):快速理解ASCII、Unicode、GBK和UTF-8
今天中午,我突然想搞清楚 Unicode 和 UTF-8 之间的关系,就开始查资料。 这个问题比我想象的复杂,午饭后一直看到晚上9点,才算初步搞清楚。 下面就是我的总结,主要用来整理自己的思路。我尽量写得通俗易懂,希望能对其他朋友有用。毕竟,字符编码是计算机技术的*石,对于程序员来说尤其重要,字符编码的知识是必须要懂的。
105 0
|
存储 JavaScript 程序员
【字符编码详解】ASCII、GB2312、GBK、UTF-8、UTF-16编码与Unicode字符集
【字符编码详解】ASCII、GB2312、GBK、UTF-8、UTF-16编码与Unicode字符集
904 0
|
存储 自然语言处理
最基础的ASCII、Unicode、UTF-8一起来多了解点
最基础的ASCII、Unicode、UTF-8一起来多了解点
252 0
最基础的ASCII、Unicode、UTF-8一起来多了解点
|
存储 算法 Java
Java编码ASCII、GB2312、GBK、Unicode、UTF-8、UTF-16 编码方式详解
Java编码ASCII、GB2312、GBK、Unicode、UTF-8、UTF-16 编码方式详解
397 0
|
存储 自然语言处理
字符编码unicode,utf-8和ascii
Ascii编码 由于计算机是美国人发明的,因此,最早只有127个字符被编码到计算机里,也就是大小写英文字母、数字和一些符号,这个编码表被称为ASCII编码,比如大写字母A的编码是65,小写字母z的编码是122。
1106 0