关于编码的一些问题
来源:互联网 发布:局域网扫描软件 编辑:程序博客网 时间:2024/05/16 12:54
首先看一下ANSI编码和ASCII 编码,用google搜到这篇文章,挺好的。http://www.differencebetween.net/technology/web-applications/difference-between-ansi-and-ascii/
ASCII: American Standard Code for Information Interchange
ANSI: American National Standard Institute
基本的区别就是:
然后又看到这篇文章,也不错,http://blog.csdn.net/zj510/article/details/37877651。建议仔细阅读。
这里,我主要再介绍一下ansi,unicode和utf8
首先看一下ANSI
ANSI编码
首先在C++代码里面敲入一行代码,很简单看下图,运行一下,会发现字符串ansi里面的内存是0xb3, 0xcc, 0xd0, 0xf2, 0xd4, 0xb1.打开记事本,写入“程序员”3个字,然后save,用ultraedit看一下十六进制编码,如下图。
跟VS里面看到的一模一样。我们在看一下C++的源文件。
看16进制的源文件,可以发现源文件里面的“程序员”3个字也是ANSI编码。好像VS对于C++源文件默认的就是ANSI编码,我在VS2013里面看到有个功能可以自动检测UTF-8编码啥的。但是没有仔细研究过。
OK, 现在我们知道,在notepad里面,打入一些字符,然后save,那么默认的就是ANSI编码。在VS里面如果输入一些常量字符串,假如是纯英文的话,那应该也是ANSI编码,如果你的常量字符串里面有中文或者韩文等其他字符的话,就视情况而定了,像vs2013可能会把你的源文件转换成UTF8格式,但我知道早期的VS是不会转的还是用ANSI.所以如果你在IDE,比如VS, Eclipse,甚至XCODE等里面输入常量字符串的话,需要小心。通常如果只是英文的话,一般是没有问题的,但是如果有中文的话,要留个心眼,看你的IDE是怎么编码的。不然恐怕就会出现乱码的情况。当然如果真的有中文等字符的话,也不建议使用ANSI编码,尽可能使用UNICODE吧。
UNICODE
unicode其实有好几种,比如unicode16,unicode32啥的。通常我们在写程序的时候,说起unicode或者宽字符,一般指的就是unicode16.也就是2个字节(wchar_t)来表示一个字符。一个英文字母a使用2个字节的宽字节wchar_t来表示,一个中文也是用一个wchar_t来表示。
notepad的saveas里面有个功能,可以把当前文件保存成unicode。
同样打开notepad输入“程序员”3个字,然后点击save as,在编码那里选择unicode。如图
保存完之后,用ultraedit打开,前面两个字节FFFE,这个其实是notepad的一个标记,不用管它,看后面的6个字节。“程序员”总共是3个中文字符,那么用unicode就是6个字节,也就是0B7A8F5E5854.
OK, 现在C++程序里面敲入一行代码,如下图.从下面的图片里面可以看到unicode字符串的内存是0x7a0b, 0x5e8f, 0x5458.跟上面ultraedit里面比较。好像每两个字节都反过来了,这是何故?
其实这里有个很好玩的事情。我们直接看unicode里面的指向的内存吧。
unicode指向的是地址0x0026fb90,看内存,内存里面的数据是0b, 7a, 8f, 5e, 58, 54。跟上面ultraedit里面显示的是一致的。那么说明unicode里面在内存存放的字节流跟ultraedit里面展示的是一模一样的。那为什么用wchar_t表示的时候就反过来了呢?其实我觉得这应该是windows上面的机制,用wchar_t表示的时候就是反过来的(不知道linux上是不是也是这样?),就好象是int在内存里面存放也是逆序的。
顺便再来看一下C#吧,写几行简单代码,直接看下图:
首先我们可以看到sizeof(char)在C#里面是2.其实在C#里面并没有wchar_t这种东西。只有一个char,而它就是2个字节。这是因为C#里面用的都是unicode。C#的string里面存放的就是unicode格式。好像Java也是这样。每一个char和上面的C++的wchar_t的值一模一样。
ANSI VS Unicode
那么我们到底应该使用ANSI还是Unicode呢?我建议使用Unicode,特殊是在写windows程序的时候,因为windows的API都支持ANSI和Unicode两种,也就是我们常说的多字节和宽字节。比如CreateFileA()支持ANSI编码, CreateFileW()支持Unicode编码。如果使用Ansi的话,万一你的字符串里面含有中文,就会比较麻烦一些,比如有些时候为了换行,很难计算,以为ANSI里面英文占一个自己,中文占2个字节。如果把一个中文给劈开了,那就显示乱码了。如果使用Unicode就很方便了,因为中文,英文都是占2个字节。当然如果你的程序确定只支持英文,那用ANSI也行,毕竟用Unicode的话,会多占内存。假如一个英文字符串有100个字符,用ANSI就占用100字节,用UNICODE就是200字节。Windows的大多数API都支持ANSI和UNICODE两种,我个人比较喜欢用UNICODE版本,毕竟现在的内存动不动都4g,8g的,多耗些内存也不是什么大问题。
utf8
最后再介绍一种非常常用的编码utf8. 什么是utf-8, 看定义, UTF-8 stands for Unicode Transformation Format-8. It is an octet (8-bit) lossless encoding of Unicode characters
至于utf8的具体细节和好处,网上一搜一大堆。基本上现在的网页用的都是utf-8编码,数据库里面用的很多也是utf-8,网络传输也是很多使用utf8。反正我觉得utf8的使用率是非常高的。比如我们想把一个字符串存入本地文件的时候也可以使用utf8编码,当然也使用ANSI或者UNICODE. 这里就简单介绍一下C++和Java里面的utf8使用吧。在C++里面,现在可以使用C++11了,简单的一个例子,把一个unicode字符串转换成utf8,再把utf8转换成unicode
运行一下,可以看到utf8的字节流,然后再把utf8字节流转换成UNICODE得到unicode2,unicode2显示的也是“程序员”。如果用C#就更简单了。我们可以看到utf8编码的字节流跟C++的一模一样。
最后看一下c#源文件的编码,我这里的c#源文件编码用的是UNICODE, 看图:(好像如果有中文的话,VS会转换成utf8)
尽量不要在源代码文件里面hardcode需要显示在UI上的字符串
比如类似的代码:
这个真的不是好习惯。如果你的程序要支持其他语言的话,你就不得不修改源文件而且重新编译了。而且万一需要支持中文的话,那么就得在字符串常量里面写中文,可是有些时候又不知道源文件是用什么格式来编码的。比如源文件是用utf8编码的话,文件就来的,SetWindowText()是不支持utf8编码显示的,我们不得不先把utf8编码转换成ANSI或者UNICODE,再调用windows API。还有其他问题,比如你用VS UNICODE编码来写程序的,而另外一个人用Xcode来写程序,那么你的中文在他的Xcode里面肯定显示乱码。总之很麻烦。我觉得我们的字符串常量应该尽可能放在资源文件里面,比如C++的resource文件,C#的资源文件。Android程序也是有资源文件。这样比较好,如果要改字符串的话,改资源文件就可以了。不需要跟源代码。当然如果是一些log之类的字符串,写在源代码文件里面倒也问题不大,因为这些log通常都是英文,而且没有localization的问题。
其他编码
除了ANIS, UNICODE, UTF8之后还有很多其他的编码,但是我觉得这三种是最常用的。而且一旦掌握了这三种以后,再看其他的编码应该也是很容易了。
- 关于编码的一些问题
- 关于http 表单编码的一些问题。
- 关于BeautifulSoup编码的一些问题
- 关于数据库编码的一些问题
- 关于编码遇到的一些问题
- 关于Python编码问题的一些看法
- 关于中文编码的一些问题
- 关于python3的一些编码问题
- 编码的一些问题
- 编码的一些问题
- 关于CABAC熵编码一些问题的研究
- 关于php与mysql的一些编码乱码问题
- 关于编码的一些理解
- 关于编码的一些理解
- 关于编码的一些总结
- 关于编码的一些知识
- 关于编码的问题
- 关于编码的问题
- 多线程——生命周期
- SpringMVC、Spring和freemarker 开发指导
- 张正友标定法小结
- 阿里云短信发送
- 虚拟机字节码执行引擎(八)
- 关于编码的一些问题
- mysql对指定列进行排名
- spark性能优化一
- 3种插入排序算法(php)
- 搭建iOS自动化打包平台(利用Jenkins持续集成iOS项目)
- scipy.optimize.minimize 的优化算法(3): DFP和BFGS的证明
- 数列分段-洛谷 1181
- UVa 11624
- Access、sqlserver數據遷移過程