黑马程序员技术交流社区
标题: 整理了一个晚上,写了篇关于乱码的文章,欢迎大家来吐槽 [打印本页]
作者: kailee 时间: 2015-4-25 08:45
标题: 整理了一个晚上,写了篇关于乱码的文章,欢迎大家来吐槽
http://kai-lee.com/2015/04/24/%E6%95%B2%E4%BB%A3%E7%A0%81%E6%97%B6%E9%81%87%E5%88%B0%E7%9A%84%E4%B9%B1%E7%A0%81%E9%97%AE%E9%A2%98/字符编码字符编码趣谈开始人类用8个可以开合的晶体管来组合成不同的状态,以表示世界上的万物,他们把这称为字节。后来,人类又做了一些可以处理这些字节以及用字节来组合出的很多状态的机器——计算机。开始计算机只在美利坚,八位的字节一共可以组合出256(2的8次方)种不同的状态。美利坚人把其中的编号从0开始的32种状态分别规定了特殊的用途,一但终端、打印接收到约定好的这些字节被传过来时,就要做一些约定的动作。比如,遇上 00×10, 终端就换行,遇上 0×07 , 终端就向人们嘟嘟叫。美利坚人把这些 0×20 以下的字节状态称为控制码。他们又把所有的空格、标点符号、数字、大小写字母分别用连续的字节状态表示,一直编到了第127号,这样计算机就可以用不同字节来存储英语的文字 了。人们把这个方案叫做 ANSI 的 ASCII 编码(American Standard Code for Information Interchange,美国信息互换标准代码)。当时世界上所有的计算机都用同样的ASCII方案来保存英文字母。
来计算机发展越来越广泛,世界各国为了可以在计算机保存他们的文字,他们决定采用127号之后的空位来表示这些新的字母、符号,还加入了很多画表格时需要用下到的横线、竖线、交叉等形状,一直把序号编到了最后一个状态255。从128到255这一页的字符集被称扩展字符集。但是原有的编号方法,已经再也放不下更多的编码。
等中国人民想使用计算机做点事儿的时候,已经没有可以利用的字节状态来表示汉字,况且有6000多个常用汉字需要保存呢?于是国人就自主研发,把那些127号之后的奇异符号们直接取消掉,并规定:一个小于127的字符的意义与原来相同,但两个大于127的字符连在一起时,就表示一个汉字,前面的一个字节(他称之为高字节)从 0xA1 用到 0xF7 ,后面一个字节(低字节)从 0xA1 到 0xFE ,这样我们就可以组合出大约7000多个简体汉字了。在这些编码里,我们还把数学符号、罗马希腊的字母、日文的假名们都编进去了,连在 ASCII 里本来就有的数字、标点、字母都统统重新编了两个字节长的编码,这就是常说的全角字符,而原来在127号以下的那些就叫半角字符了。中国人民看到这样很不错,于是就把这种汉字方案叫做 GB2312 。 GB2312 是对 ASCII 的中文扩展。但是中国的汉字太多了,后来还是不够用,于是干脆不再要求低字节一定是127号之后的内码,只要第一个字节是大于127就固定表示这是一个汉字的开始,不管后面跟的是不是 扩展字符集里的内容。结果扩展之后的编码方案被称为 GBK 标准,GBK 包括了 GB2312 的所有内容,同时又增加了近20000个新的汉字(包括繁体字)和符号。后来少数民族也要用电脑了,于是我们再扩展,又加了几千个新的少数民族的字,GBK 扩成了 GB18030。
因为当时各个国家都像中国这样搞出一套自己的编码标准,结果互相之间谁也不懂谁的编码,谁也不支持别人的编码。当时的中国人想让电脑显示汉字,就必须装上一个”汉字系统”,专门用来处理汉字的显示、输入的问题,装错了字符系统,显示就会乱了套。这怎么办?
就在这时,一个叫 ISO (国际标谁化组织)的国际组织决定着手解决这个问题。他们采用的方法很简单:废了所有的地区性编码方案,重新搞一个包括了地球上所有文化、所有字母和符号的编码!他们打算叫它Universal Multiple-Octet Coded Character Set,简称 UCS, 俗称 UNICODE 。UNICODE 开始制订时,计算机的存储器容量极大地发展了,空间再也不成为问题了。于是 ISO 就直接规定必须用两个字节,也就是16位来统一表示所有的字符,对于 ASCII 里的那些半角字符,UNICODE 包持其原编码不变,只是将其长度由原来的8位扩展为16位,而其他文化和语言的字符则全部重新统一编码。由于半角英文符号只需要用到低8位,所以其高 8位永远是0,因此这种阔气的方案在保存英文文本时会多浪费一倍的空间。UNICODE 是用两个字节来表示为一个字符,他总共可以组合出65535不同的字符,这大概已经可以覆盖世界上所有文化的符号。
UNICODE 来到时,一起到来的还有计算机网络的兴起,UNICODE 如何在网络上传输也是一个必须考虑的问题,于是面向传输的众多UTF(UCS Transfer Format)标准出现了,顾名思义,UTF8 就是每次8个位传输数据,而 UTF16 就是每次16个位,只不过为了传输时的可靠性,从 UNICODE 到 UTF 时并不是直接的对应,而是要过一些算法和规则来转换。这种转换,这里就不再赘述了。
简单的总结关于字符集(character set)和编码(encoding),对于 ASCII、GB 2312、Big5、GBK、GB 18030 之类的遗留方案来说,基本上一个字符集方案只使用一种编码方案。比如 ASCII 这部标准本身就直接规定了字符和字符编码的方式,所以既是字符集又是编码方案;而 GB 2312 只是一个区位码形式的字符集标准,不过实际上基本都用 EUC-CN 来编码,所以提及「GB 2312」时也说的是一个字符集和编码连锁的方案;GBK 和 GB 18030 等向后兼容于 GB 2312 的方案也类似。
对于 Unicode,字符集和编码是明确区分的。Unicode/UCS 标准首先是个统一的字符集标准。而 Unicode/UCS 标准同时也定义了几种可选的编码方案,在标准文档中称作「encoding form」,主要包括 UTF-8、UTF-16 和 UTF-32。所以,对 Unicode 方案来说,同样的基于 Unicode 字符集的文本可以用多种编码来存储、传输。所以,用「Unicode」来称呼一个编码方案不合适,并且误导。
乱码产生原因及解决乱码的产生以 Windows 为例,Windows 里说的「ANSI」其实是 Windows code pages,这个模式根据当前 locale 选定具体的编码,比如简体中文 locale 下是 GBK。我们可以看一下进入 DOS 窗口输入: chcp 可以得到操作系统的代码页信息,你可以从控制面板的语言选项中查看代码页对应的详细的字符集信息。我查的活动代码页为:936,它对应的编码为 GBK 。当你在 windows 系统下编写完代码保存的时候,一般会保存为系统默认的编码格式,这样一来如果你的代码源文件编码格式与你的编译器所解析的编码格式不同当然就会报错了。
解决方法这个问题不难解决,你在保存代码文件的时候选择保存为编译器能够解析的格式就通过编译了。但是你会发现,编译出来运行一下发现控制台显示的依然是乱码!!!Why?那是因为控制台显示的时候缺省的是使用系统默认的字符集,中国在 windows 下的话默认 GBK ,编译之后的可执行文件假设是 UTF-8 的,系统会以识别GBK一样对待 UTF-8 当然会出现乱码了!
搞懂了乱码产生的原因,那么不难得找到解决问题的办法,你想修改成什么格式的都OK,关键是要统一,并不是像网上一些人说的,修改成 GBK 啦,修改成UTF-8啦,其实关键是你自己要知道自己在干什么。涉及兼容性考量时,不要用记事本,用专业的文本编辑器保存为不带 BOM 的 UTF-8。我用的是 Sublime Text3,挺好用的而且基本上没再遇到过乱码问题。 明白了其中的原理就 OK!!!
作者: 麻木 时间: 2015-4-25 09:22
一开始的逻辑开关元件是电子管把
作者: wzboy 时间: 2015-4-25 14:25
楼主说的很详细,关键是 我还真看完了
作者: kailee 时间: 2015-4-28 16:35
哈哈,最近忙着看视频,总结,没及时回复,有问题多交流啊
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) |
黑马程序员IT技术论坛 X3.2 |