转自:http://blog.csdn.net/yulongli/article/details/22952127这里说一下因为编码带来的存储问题。
存储有两层含义,一是指落地成文件存储,这种情况一般用户都会遇到;另外一层指的是在内存中的存储,这是程序员要考虑的事情。 因为字符编码有好多种,如果一段文本中有非ASCII字符,就必须得用某一种字符编码来表示,将其保存到文件中也是如此。 现在要打开一个文本文件,文件编辑器(记事本,EditPlus等)必须要知道这个文件采用了何种编码,不然没法解析。如果文件是UTF-8编码存储,却被当作GBK编码来解读,最后展示出来肯定会是乱码。 我们先说Windows操作系统下面的情况,GBK是中文版Windows默认的兼容ASCII码的存储格式,所以GBK编码不用特殊标识。只不过这样的文件放到台湾版或是日本版的系统下面打开会是乱码。UTF-8编码的文件就需要特殊处理一下,Windows会在UTF-8编码的文件前增加3个字节的特殊字符"EF BB BF” ,这就是常说的BOM,全称叫做"Byte Order Mard”。 只是,BOM是为其他编码准备的,UTF-8带BOM并不合标准,只在Windows阵营下才这么用。由于Windows的影响范围太广,很多文本编辑器都是支持带BOM的UTF-8文本。在Mac和Linux下就不吃这一套,很有可能会出现乱码。大部分编译器也不认,遇到问题会直接编译错误。 我们可以用Windows自带的记事本来存储不同格式的文本并进行比较。打开记事本,输入一段文本,比如就三个字“中国人”,保存时可以指定编码,如下图: 保存完后我们来看分别选择ANSI 、 Unicode 和 UTF-8 这三种情况下文件的具体内容,可以用UltraEdit打开看文件看其16进制表示,也可以用Linux下面的xxd工具。 用GBK 编码保存后的文件内容如下: 0000000: d6d0 b9fa c8cb …… 可以看到“中国人”三个字的GBK编码分别是“d6 d0”, “b9 fa”, “c8 cb” 用UTF-8编码保存后的文件内容如下: 0000000: efbb bfe4 b8ad e59b bde4 baba ………… 可以看到“中国人”三个字的UTF-8编码分别是“e4 b8 ad” “e5 9b bd” “e4 ba ba”, 前面多出来的3个字节是BOM。 如果在Mac下面重新保存一个文件,里面的内容是这样的,没有BOM,“0a”是最后多了一个换行符 0000000: e4b8 ade5 9bbd e4ba ba0a ………. 用Unicode编码保存后的文件内容如下: 0000000: fffe 2d4e fd56 ba4e ..-N.V.N “中国人”三个字的Unicode编码分别是 “0x4E2D” “0x56FD”, “0x4EBA” 其中fffe代表该文件是little endian存储的,如果是feff,说明是big endian 存储的。 看到这里大家可能又奇怪了,怎么GBK 跟UTF-8的编码跟展示那么对应,Unicode展示出来就高低位互换了呢? 这里要格外注意,GBK和UTF-8的基本单位是byte,是一个字节,编辑器对其解析时是顺序的。我们看到的从左到右在地址空间里面是由低位到高位。“中”的GBK编码就就是0xd6和0xd0两个字节拼起来表示。但Unicode的基本单位是short,也就是两个字节,“中”的Unicode表示是”0x4E2D”, 2D在低位,用little endian存储当然是在左边了。 Mac 下面默认是big endian存储,用Unicode编码保存后的文件内容如下: 0000000: 4e2d 56fd 4eba 000a N-V.N… 可以看到2D跑到右边去了。这里最后面的“000a” 是Unicode表示的换行符,其在正常ASCII码的前面增加了8位的0。 再说一下HTML页面,也就是我们平常说的网页。在文件开头有meta标签可以设置charset,这是设置本页面编码的地方,它的值可以为"utf-8”,”gb2312”等。charset一定要在文件开头,在任何非ASCII码出现之前设置好,否则很有可能出现乱码。另外,如果是UTF-8格式存储,BOM是不需要的。有些浏览器碰到带BOM的页面会解析出错。 比如下面这个HTML页面的代码。
网络上还有一种XML文件使用的很频繁,其编码的设置跟HTML文件差不多,也是在开头设置encoding。不过对于web开发工程师来说,如果是利用xml实现ajax请求,后台返回给前端的xml数据可以不必太纠结编码,统一用unicode的转义字符来表示就可以了。浏览器自己可以正常解析,这部分内容我们后续再详细介绍。 比如下面这个xml文件,不论encoding设置成gb2312还是utf-8,浏览器都可以正常显示。
只是这种情况如果是程序员写代码来解析的话,最好还是将所使用的编码格式跟charset声明的保持一致。
第一种: the length of str is 6 D6 D0 B9 FA C8 CB 第二种: the length of str is 9 E4 B8 AD E5 9B BD E4 BA BA 之所以会出现这两种情况,就是因为str所指向的字符串其内容受源代码文件的编码格式影响,如果是以gbk编码保存,则执行结果是第一种情况,如果是用utf-8编码保存,就是第2种情况。 为了使编码固定,可以在定义时明确编码,比如我就是想定义一个utf8格式的编码,可以这么定义:
|
|