[温故而知新]
最近在写网络数据传输的程序,被各种编码搞的一塌糊涂,在这里简单记录如下:
1. ASCII和Ansi编码
字符内码(charcter code)指的是用来代表字符的内码.读者在输入和存储文档时都要使用内码,内码分为
a.单字节内码 -- Single-Byte character sets (SBCS),可以支持256个字符编码.
b.双字节内码 -- Double-Byte character sets (DBCS),可以支持65000个字符编码.
前者即为ASCII编码,后者对应ANSI。在简体中文的操作系统中ANSI就指的是GB2312,代码页936(ANSI下不同语言有不同的代码页)。
2.GB2312和GBK编码
GB2312是对 ANSI 的简体中文扩展。GB2312共收录了七千个字符,由于GB2312支持的汉字太少而且不支持繁体中文,所以GBK对GB2312进行了扩展,以支持繁体中文和更多的字符,GBK共支持大概22000个字符,GB18030是在GBK的基础上又增加了藏文、蒙文、维吾尔文等主要的少数民族文字。
代码页(codepage) 就是各国的文字编码和Unicode之间的映射表。例如GBK和Unicode的映射表就是CP936,所以也常用cp936 来指代GBK。
3.Unicode
ANSI有很多代码页,使用不同代码页的内码无法在其他代码页平台上正常显示。由于各国之间的编码不同造成的交流传输不便,ISO 打算废除所有的地区性编码方案,重新建立一个全球性的编码方案把所有字母和符号都统一编码进去,称之为 "Universal Multiple-Octet Coded Character Set",简称为 UCS(ISO10646)。同时又有unicode.org这个组织也制定了自己的全球性编码 unicode,自从unicode2.0开始,unicode采用了与USC相同的字库和字码,阶段主要采用的是
UCS-2/unicode 16 位的编码。
4.UTF编码
UTF(Unicode/UCS Transfer Format),UCS 变长存储的编码方式,主要用来解决 UCS 编码的传输问题的。分为 UTF-7,UTF-8,UTF-16,UTF-32 等。UTF-8是一次传输8位(一个字节)的UTF编码方式,一个字符可能会经过1-6次传输,具体的跟 unicode/UCS 之间的转换关系如下:
unicode(U+) |
utf-8 |
U+00000000 - U+0000007F:
|
0xxxxxxx
|
U+00000080 - U+000007FF:
|
110xxxxx10xxxxxx
|
U+00000800 - U+0000FFFF:
|
1110xxxx10xxxxxx10xxxxxx
|
U+00010000 - U+001FFFFF: |
11110xxx10xxxxxx10xxxxxx10xxxxxx
|
U+00200000 - U+03FFFFFF: |
111110xx10xxxxxx10xxxxxx10xxxxxx10xxxxxx
|
U+04000000 - U+7FFFFFFF: |
1111110x10xxxxxx10xxxxxx10xxxxxx10xxxxxx10xxxxxx
|
比如: "我" 的unicode/UCS编码为 "U+6211"(01100010 00010001),在U+00000800 - U+0000FFFF之间,所以采用三字节编码,按规则分段为:0110 001000 010001,再分别替换上表中的x,得到11100110 10001000 10010001,即为 "E6 88 91",这就是 "我" 的UTF-8编码。
举个有趣的例子:
在 Windows 的记事本里新建一个文本文件,输入"联通"两个字,保存,关闭,再次打开,会发现文本已经不是"联通"了,而是几个乱码。
当使用记事本新建文件时,默认的编码是 ANSI,输入中文就是 GB 系列的编码,"联通" 两字的编码为:
c1 1100 0001
aa 1010 1010
cd 1100 1101
a8 1010 1000
注意到了吗?第一二个字节、第三四个字节的起始部分的都是 "110" 和 "10",正好与 UTF-8 规则里的两字节模板是一致的,于是再次打开记事本时,记事本就误认为这是一个UTF-8编码的文件,让我们把第一个字节的110和第二个字节的10去掉,我们就得到了"00001 101010",再把各位对齐,补上前导的0,就得到了 "0000 0000 0110 1010",这是 UNICODE 的 006A,也就是小写的字母 "j",而之后的两字节用 UTF-8 解码之后是0368,这个字符什么也不是。这就是只有
"联通" 两个字的文件没有办法在记事本里正常显示的原因。
而如果你在 "联通" 之后多输入几个其他字,其他的字的编码不见得又恰好是 110 和 10 开始的字节,这样再次打开时,记事本就不会坚持这是一个 UTF-8 编码的文件,而会用 ANSI 的方式解读之,这时乱码又不出现了。
5.UTF-16
UTF-16是一次传输两个字节的UTF编码方式,现如今Unicode/UCS也主要采用16位编码,所以UTF-16的存储方式和Unicode/UCS的编码方式也相同。确切的说是和UCS-2/unicode 16的编码方式相同。
6.big endian 和 little endian
在UTF-16或者UCS的编码中经常遇到这两个选项,big endian 和little endian 是CPU处理多字节数的不同方式。例如“汉”字的 Unicode/UCS 编码是 6C49。那么写到文件里时,究竟是将 6C 写在前面,还是将 49 写在前面?如果将 6C 写在前面,就是big endian。还是将 49 写在前面,就是little endian。
BOM 称为 "Byte Order Mark"。UTF-8 以字节为编码单元,没有字节序的问题。而 UTF-16 以两个字节为编码单元,在解释一个 UTF-16 文本前,首先要弄清楚每个编码单元的字节序。例如收到一个 "奎" 的 Unicode/UCS 编码是 594E,"乙" 的 Unicode/UCS 编码是 4E59。如果我们收到 UTF-16 字节流 "594E",那么这是 "奎" 还是 "乙"?
在Unicode/UCS编码中有一个叫做 "ZERO WIDTH NO-BREAK SPACE" 的字符,它的编码是FEFF。而FFFE在Unicode/UCS中是不存在的字符,所以不应该出现在实际传输中。UCS规范建议我们在传输字节流前,先传输字符 "ZERO WIDTH NO-BREAK SPACE"。这样如果接收者收到
FEFF,就表明这个字节流是Big-Endian 的;如果收到FFFE,就表明这个字节流是Little-Endian的。因此字符 "ZERO WIDTH NO-BREAK SPACE" 又被称作 BOM。
UTF-8 不需要 BOM 来表明字节顺序,但可以用 BOM 来表明编码方式。字符 "ZERO WIDTH NO-BREAK SPACE" 的 UTF-8 编码是 EF BB BF。所以如果接收者收到以 EF BB BF 开头的字节流,就知道这是 UTF-8 编码了。Windows 就是使用 BOM 来标记文本文件的编码方式的。
分享到:
相关推荐
require "lc" print(lc.help());... u2w(utf8 to unicode) w2a(unicode to ansi) w2u(unicode to utf8) u2a(utf8 to ansi) a2u(ansi to utf8) bstr(bytes of str) help(show this) wunoman@qq.com 2012/03/06
从其他地方搜集的别人的作品,我觉得写的通俗,实用。与大家分享下。
ANSI --> UTF-8 Unicode --> ANSI Unicode --> UTF-8 UTF-8 --> ANSI UTF-8 --> Unicode UTF-8 --> Unicode big endian ansi转别的,不检验BOM,一律作为ansi编码进行转换 unicode转别的,首先检验BOM,不合格不...
utf-8、ANSI、Unicode相互转化c++实现 std::string ConverANSI2UTF8(const std::string & str); std::wstring ConverANSI2Unicode(const std::string str); std::wstring ConverUTF82Unicode(const std::string str)...
Txt文件编码批量转换器用于批量转换txt文本文档的编码格式。通常,我们电脑里的txt文件都是ASNI编码,当放到手机或MP3里时,打开看到的往往...目前,它支持ASNI、UTF-8、Unicode和Unicode big endian等编码的相互转换。
php 字符编码转换类,支持ANSI、Unicode、Unicode big endian、UTF-8、UTF-8+Bom 互相转换。
提供了ANSI,UNICODE,UTF8三种不同编码方式之间的互相转换;使用方便。
自己写的ANSI UNICDE 和UTF 8编码的转换。轻松实现三种编码的转换。
查看文本文件的编码方式 UTF8 ANSI UNICODE 在qt下编译通过
各种编码UNICODE、UTF-8、ANSI、ASCII、GB2312、GBK详解
比如utf8转gbk,gb2312转utf8,ansi转utf8,utf8 unicode 转换,utf8转换gb2312,utf16、utf32、utf8编码转换,gbk转换utf8,utf8 ascii转换。 2 强大正则表达式支持字符编码转换软件 是唯一同时支持用正则表达式匹配和...
ANSI转Unicode Unicode转ANSI UTF8转Unicode Unicode转UTF8 wchar_t* 转 char* char*转 char* UTF8转ANSI ANSI转UTF8
(包括ANSI、UNICODE、UNICODE big endian、UTF-8)格式的文本文件 */ //核心算法:CStdioFileEx继承自CStdioFile, 覆盖CStdioFile的 BOOL ReadString(CString& rString)方法, // 根据不同文件编码特征,寻找文件...
终于找到了,之前有发过只能ANSI编码转Unicode编码,这次是多个工具合集,包括CMD环境中用命令方式实现ANSI编码文本文件转为Unicode、Unicode转ANSI……呵呵太好了!
UTF8-UNICODE-ANSI之间相互转换的小工具,很适用的。
打开txt文件,自动识别编码格式ansi,unicode,unicode-BE,utf8,utf8-BOM,并转换为unicode显示到edit
Unicode一种压缩形式,英文A在unicode中表示为0x0041,老外觉得这种存储方式太浪费,因为浪费了50%的空间,于是就把英文压缩成1 个字节,成了utf8编码,但是汉字在utf8中占3个字节,显然用做中文不如ansi合算,这...
文本文件编码转换:ANSI、Unicode、UTF-8三种存储编码相互转换。 Unicode作为源文件同时支持Big endian,作为目标文件不支持Big endian。 UTF-8不支持无BOM的文件。 希望能对新手有帮助,也大家多提宝贵意见。
2 支持ANSI,Unicode,UTF-8等编码互换 3 可以设置无限个书签(9种图标可换)轻松定位 4 空格,制表符彩色显示,并可互相转换 5 可以对任意的文本块进行操作,ALT键+鼠标 6 对括号{}〔〕()可以高亮配对...
C++Builder String,UNICODE,UTF8,ANSI互转的类,类的互相转换