字符编码再次剖析

这几天一直在研究字符编码,也学到了不少的知识,现在在此进行细细总结。转载请注明出处。

首先引用一段网上对字符编码的风趣解释:


问:计算机是怎么表示文字的? 他不会. 他就会说0和1.
于是乎 有一帮人为了表示字母和各种符号,就发明了ASCII 实际上就是固定了.一个八位的字节固定的01排列来表示固定的字符.
比如.字母A 的ASCII码就是.65. 这个排列就是.01000001.当然,这只是ASCII的编码,同样呢,有好多好多种编码,当然道理是一样的. 当你要把这个串"A",发送到别的机器,千万要记住,你发的不是文本"A",你发过去的是一串01000001(ASCII的时候).


那么现在我们就要好好理解一下字符和字节的概念了,一个字符可以由任意整数个字节进行表示,这也就是说,一个字符可以由一个字节表示,也可以由多个字节表示,如在ASCII中一个字符由一个字节组成,而gb2312和ASCII兼容,而且由两个字节来表示中文,gbk是gb2312的超集,这也就意味着gb类的字符编码是变长存储的。而unicode(默认的实现方式是小头存储,即ucs-2)每个字符是由两个字节存储的,且字符的第二个字节在存储的时候放在前面,而且通过补0和ascii形成假兼容,unicode big endian即所谓的大头存储,即字符的第一个字节放在前面。这两种unicode的存储方式造成了存储空间的浪费,而且与ascii是假兼容的。而utf-8解决了上述的两个问题,目前windows下的默认编码方式是ansi,即gbk,在vc6.0下是ansi,而在vs2010已经采用了utf-8的编码方式。

在这里我们可以使用ultraedit的十六进制查看工具来查看不同编码的文件的存储结构。分别将一个有相同的文本内容的文本文件另存为ansi编码,unicode编码,unicode big endian编码和utf-8编码的文件并且用ultraedit打开,切换至十六进制视图下,进行查看。可以看到,ansi文件没有前缀,ascii字符用一个字节,而中文用两个字节。而unicode编码的文件有前缀FF FE,unicode big endian有文件前缀FE FF,而且可以看到不管任何字符都用两个字节表示,其中有很多的00字节,这势必会在c语言中字符串的操作上带来很大的不便。utf-8有文件前缀EF BB BF,而且中文是用三个字节表示的。可以通过查看vc和vs生成的文件来查看其不同的编码方式。


现在我有一个中英文混合的utf-8编码的文件,想逐行打印其中的每一个字符,那么可以使用下面的程序:

string path = "C:\\Users\\Yelbosh\\Desktop\\tem.txt";
            System.IO.StreamReader sr = new System.IO.StreamReader(path, Encoding.UTF8);
            string tempstr = sr.ReadToEnd();
            foreach (char tempc in tempstr)
            {
                Console.WriteLine(tempc.ToString());
            }
这里其他编码方式的文件当然也可以,我们最主要使用的是foreach函数,这里可以通过streamreader按照不同的编码方式解析文件的内容。


C#也提供了很多的方法来进行不同编码方式之间的字节数组的转换。使用encoding的convert方法可以在不同的编码方式之间进行转换。

 string str = "你好吗我其实h好的i";
            System.Text.Encoding gb2 = System.Text.Encoding.GetEncoding("GB2312");
            byte[] b1 = gb2.GetBytes(str);
            /*
            foreach (byte b in b1)
            {
                Console.Write(b.ToString("X2")); Console.Write("\t");
            }
            
            Console.Write("\n");
             *  * */
            System.Text.Encoding uni = System.Text.Encoding.GetEncoding("Unicode");
            string msg = uni.GetString(System.Text.Encoding.Convert(gb2, uni, b1));
            Console.Write(msg);

通过实验我们可以得出正确的结论。其实我们也可以看出字符串的显示已经脱离了底层,已经不属于编码方式的范畴了。


但是c#并没有给出源代码,那么计算机如何进行不同编码方式之间的转换呢?它是怎么识别变长存储呢?如何用c++编写不同字符编码方式之间的转换呢?请继续关注该博客~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值