移动比联通强?
在简体中文Windows系统中:
1.打开记事本,输入“移动”,保存关闭后重新打开,显示的仍然是“移动”两个字。
2.重新新建一个文本文件,输入“联通”,保存关闭后重新打开,显示的就不是“联通”字符了,而是看上去所谓的乱码。
的确,这就是一个编码问题。
编码问题由来
ASCII
字符需要编码,一套编码体系就形成了一个字符集。美国人最开始只创造了一个字符集,也就是ASCII字符集,ASCII字符集,长8位,首位为0。后来欧洲国家发现128个字符不够用,想利用ASCII后128位,128位还是满足不了所有欧洲国家的要求,就对后128个字符进行分片,形成了iso-8859系列字符集,包括iso-8859-1,iso-8859-2等。
GB2312,GBK和GB18030
计算机来到中国后,又催生了GB2312编码标准,GB2312没有包括繁体字,后又扩展成为GBK(GB13000),GBK是GB2312的“超集”。GB2312和GBK编码标准中,存储方法兼容ASCII,汉字占用两个字节。2000年和2005年又发布了GB18030-2000和GB18030-2005编码标准,存储方法中有单字节、双字节和四字节三种方式对字符编码进行存储。平时说的ANSI编码,都是根据不同的国家和地区而不同的标准。在简体中文系统下,ANSI 编码代表 GBK 编码,在日文操作系统下,ANSI 编码代表 JIS 编码。 不同 ANSI 编码之间互不兼容,当信息在国际间交流时,无法将属于两种语言的文字,存储在同一段 ANSI 编码的文本中。
Unicode
历史介绍省略数百字。。。
Unicode基于通用字符集(Universal Character Set)的标准来发展,是国际组织制定的可以容纳世界上所有文字和符号的字符编码方案。Unicode用数字0-0x10FFFF来映射这些字符,最多可以容纳1114112个字符,或者说有1114112个码位。码位就是可以分配给字符的数字。
(UCS-2用两个字节编码, UCS-4用4个字节编码。UCS-4根据最高位为0的最高字节分成2^7=128个group。每个group再根据次高字节分为256个平面(plane)。每个平面根据第3个字节分为256行 (row),每行有256个码位(cell)。group 0的平面0被称作BMP(Basic Multilingual Plane)。将UCS-4的BMP去掉前面的两个零字节就得到了UCS-2。每个平面有2^16=65536个码位。)
Unicode & GBXXX?
Unicode和GBXXX是两套不同的编码标准,字符的码位不相同,如果需要转换,必须要同时知道一个字符在两个编码中的码位。
编码简介
UTF-8
Unicode是编码标准,并没有规定字符的存储方式。UTF-8、UTF-16、UTF-32都是将Unicode标准中的码位转换到具体存储数据的方案。总之,任何一个编码标准和具体的字符存储方案是分离的,只要存储后的编码还能映射到原始的编码标准中的码位。
为什么不直接用Unicode的UCS-2码位来直接当作字符存储的数据编码呢,一是为了考虑和ASCII的兼容性,二是对属于ASCII的字符用Unicode编码太占用空间。UTF-8就是在这样的情况下诞生了。UTF-8只是一种编码的存储方案,从一个字符的UTF-8编码可以找到唯一对应的Unicode码位。
简单介绍下UTF-8,UTF-8以字节为单位对Unicode进行编码。从Unicode到UTF-8的编码方式如下:
Unicode编码(16进制) ║ UTF-8 字节流(二进制)
000000 - 00007F ║ 0xxxxxxx
000080 - 0007FF ║ 110xxxxx 10xxxxxx
000800 - 00FFFF ║ 1110xxxx 10xxxxxx 10xxxxxx
010000 - 10FFFF ║ 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
UTF-8的特点是对不同范围的字符使用不同长度的编码。对于0x00-0x7F之间的字符,UTF-8编码与ASCII编码完全相同。UTF-8编码的最大长度是4个字节。从上表可以看出,4字节模板有21个x,即可以容纳21位二进制数字。Unicode的最大码位0x10FFFF也只有21位。
例:“汉”字的Unicode编码是0x6C49。0x6C49在0x0800-0xFFFF之间,使用用3字节模板了:1110xxxx 10xxxxxx 10xxxxxx。将0x6C49写成二进制是:0110 1100 0100 1001, 用这个比特流依次代替模板中的x,得到:11100110 10110001 10001001,即E6 B1 89。
判断一个文本编码是否是UTF-8编码的最简单的正则:
/^([\x01-\x7f]|[\xc0-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xf7][\x80-\xbf]{3})+$/
上述正则并不是100%能够判断正确的。事实上也没有100%正确的方法。一个Bad Case就是文章开头提到的“联通”例子,“联通”的GBK编码是c1 aa cd a8,刚好符合了上述的正则表达式,被Windows记事本认为是UTF-8来编码了。
联通的Bad Case还不是最Bad的,假如c1 aa cd a8是UTF-8编码,c1 aa对应到Unicode的十六进制表示是6A(字符j),只需要一个字节就可以表示了。所以c1 aa不是一个规范的UTF-8编码,虽然c1 aa可以通过简单的正则表达式验证。
下面是一个更Bad的Case,记事本输入“伞”,关闭后再打开,就变成拉丁字符ɡ了,对于这样一个文本文件,如果不额外告诉程序是什么编码的,程序当UTF-8和当GBK来处理都不是程序的错了。
那么哪些汉字会引起当作UTF-8来误读的情况呢?根据正则表达式和GBK的编码情况(全国信息技术标准化技术委员会汉字内码扩展规范(GBK)码:http://www.snwei.com/studypc/write/009.htm ),在[\xc0-\xdf][\x80-\xbf]之间的GBK编码的汉字都可能会有问题,只要GBK编码的文本文件中的字符都是落在这个范围内(包括有任意的其它ASCII字符的情况,比如“伞1”也会被当作UTF-8来处理),都会出现编码难以或者不能判断的情况。
UTF-8的编码就介绍到这儿,没有什么准确判断UTF-8编码的方法,isUTF8Encode这样的函数如果返回值是二值的,都是有例外的。到可以写个判断肯定不是UTF-8编码的方法。
BOM
BOM——Byte Order Mark,中文名译作“字节顺序标记”。在UCS 编码中有一个叫做 "Zero Width No-Break Space" ,中文译名作“零宽无间断间隔”的字符,它的编码是USC编码是FEFF。而FFFE 在 UCS 中是不存在的字符,所以不应该出现在实际传输中。UCS 规范建议我们在传输字节流前,先传输字符 "Zero Width No-Break Space"。这样如果接收者收到 FEFF,就表明这个字节流是 Big-Endian 的;如果收到FFFE,就表明这个字节流是 Little- Endian 的。因此字符 "Zero Width No-Break Space" (“零宽无间断间隔”)又被称作 BOM。
UTF-8 不需要 BOM 来表明字节顺序,但可以用 BOM 来表明编码方式(不知道是不是MS干的)。字符 "Zero Width No-Break Space" 的 UTF-8 编码是 EF BB BF。所以如果接收者收到以 EF BB BF 开头的字节流,就知道这是 UTF-8编码了。Windows 就是使用 BOM 来标记文本文件的编码方式的。所以UTF-8一般有两种,一个是UTF-8 with BOM,一个是UTF-8 without BOM。linux下的非常多的程序都是不认UTF-8 with BOM的,另外PHP也是不认的,只要有BOM的UTF-8,PHP(最新版本是否支持BOM未验证)就会出错。
不过用BOM也会有Bad Case,“锘胯创”三个字在记事本中以GBK保存后再打开就变成了UTF-8的“贴”。不要在UTF-8中保存BOM头。如果在程序的输出中看到字符“锘”就要格外注意,很有可能是UTF-8 with BOM的编码被当作GBK的来处理了。
小结
个人认为GBK的主要优势在于Web页面和减少磁盘IO,GBK能够节省实实在在的带宽,假设一个web请求可以省下100个字节,那么100万/秒的访问下,能够节省100MB/s的带宽了。也许服务器可以支撑更大规模的请求访问,处理更多的数据,但是带宽不见得够用。
对于输入输出中有字符串的,最好都明确告知编码。程序自身内部的编码可以统一,而在输入输出的时候按要求进行转码。
参考文献
http://www.unicode.org/charts/
http://baike.baidu.com/view/40801.htm
http://www.hudong.com/wiki/gbk
相关推荐
该工具用于字符编码UTF8转GB2312,可批量转换。只需将该工具放置与需要转换文件的目录下,双击运行即可。 注意:需安装Python,Python 2和3 需安装通用编码检测器,文件内有安装方法; 该工具对于入门学习Python 也...
由于Python源文件本身是按UTF-8编码的,所以处理中文字符不会出现太多问题,但为了确保Python脚本在不同环境和版本下都能正确处理中文字符,最好在文件的开头声明编码。 对于初学者,了解如何在Python脚本中输出...
该工具用于字符编码GB2312转UTF8,可批量转换。只需将该工具放置与需要转换文件的目录下,双击运行即可。 注意:需安装Python,Python 2和3 需安装通用编码检测器,文件内有安装方法; 该工具对于入门学习Python 也...
- **简化操作**:如果允许多种编码共存,则即使是简单的字符串操作也会变得复杂,比如连接一个GB2312编码的字符串和一个UTF-8编码的字符串时,很难确定最终结果应采用哪种编码。 - **确保一致性**:统一编码格式...
1. 读取UTF-8编码的网页内容:可以使用易语言的文件操作命令,如“读文本文件”或“读网络文件”,获取网页的UTF-8编码字符串。 2. 分析UTF-8编码:UTF-8编码的特点是首位标识字节的最高位,根据这些位可以确定字符...
- 字符编码:ASCII码、Unicode(UTF-8)及汉字编码。 - 浮点数表示:IEEE 754标准。 - 存储单位:字节、KB、MB、GB、TB等。 3. **第八章:操作系统基础**: - 操作系统定义与功能:进程管理、内存管理、文件...
- 支持单字节编码和UTF-8编码。 - 原生支持MySQL和PostgreSQL。 2. **Sphinx在Windows上的安装步骤**: - 访问官方网站下载最新Windows版本,如Win32 release binaries with MySQL support。 - 解压缩到指定...
- 对于Qt5.0以下版本,在`main.cpp`中修改编码方式为UTF-8: ```cpp #include int main(int argc, char *argv[]) { QApplication a(argc, argv); QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8...
在某些情况下,Qt Creator可能会报告无法识别文件编码为UTF-8的问题。此时,可以通过以下方式解决: 1. 打开Qt Creator中的文件。 2. 在文件菜单下选择“重新加载”。 3. 选择GB2312编码格式。 4. 修改`main.cpp`...
- **编码转换:**支持多种字符编码,包括ASCII、Unicode、UTF-8等,方便跨平台和跨编码格式的工作。 - **行号显示与书签:**显示行号以便于定位,设置书签则可以快速跳转到重要位置。 2. **高级编程与开发辅助:*...
因为我的 jsp 和 html 文件都是 UTF-8 编码的, 所以我在 param-value 标签中设置了 UTF-8. 估计你使用的是 GB2312 或者 GBK, 立即转到 UTF-8 上来吧. 分解配置文件. context-param 标签指明我们的配置文件还有 /...
- 主要编码标准: GB2312, UTF-8, UTF-16, UTF-32 - Unicode 码: 一种广泛使用的字符编码标准, 能够覆盖几乎所有语言的文字 **5. 运算符** - **算术运算符**: `+`, `-`, `*`, `/`, `%` - **自增减运算符**: `++`, `-...
- 注意:如果文档使用的是UTF-8编码,在Windows环境下输出可能会出现乱码问题,因为默认控制台编码为gb2312。 - **保存文档对象**: - `TiXmlDocument`还提供了`SaveFile`方法用于保存文档到新的文件。 ```cpp ...
随着信息技术的发展,为了容纳更多国家的文字,出现了多种编码格式,如UTF-8、GB2312、GBK和CP936等。 - **UTF-8** 是一种可变长度的编码,可以表示全世界所有国家的字符,它使用1到4个字节来编码一个字符,英文...
**字符编码:UTF-8和GBK** 在处理文本文件时,字符编码是个关键问题。"UTF-8"是一种广泛使用的Unicode编码,支持世界上几乎所有的字符集,包括中文。"GBK"是中国大陆的国家标准,是对GB2312的扩展,也包含了大量...
3. 编码转换:在不同环境下,可能需要将GB2312编码转换为其他编码格式,如UTF-8,以便在不同的系统或软件间兼容。易语言提供了转换编码的函数,可以实现不同编码间的转换。 4. 错误处理:在处理汉字编码时,可能会...
例如,可以将Unicode字符串转换为UTF-8或GB2312编码的字节序列。 - **`decode()`**:将字节序列转换回字符串。此过程可能会遇到无法解码的字节,可以通过设置`errors`参数来处理这些情况,如`errors='ignore'`忽略...
- Python中,二进制(0/1)可以转换为ASCII,进一步转换为各种字符编码,如GB2312、GBK、GB18030,最通用的是Unicode,最终以UTF-8编码存储和传输。 - `chr()` 和 `ord()` 函数分别用于将二进制转换为字符和字符...
- 示例代码中的某些属性(如`<meta http-equiv="Content-Type">`中的`gb2312`字符集)已经不再推荐使用,建议采用UTF-8编码。 - 在实际项目中,还需要关注浏览器兼容性问题,确保网站能够在不同的浏览器和设备上...