最近接了一个单是需要把非 UTF-8 (No BOM)编码的文件转换成 UTF-8 (No BOM),若此文件是 UTF-8 但带有 BOM ,需要转换成不带 BOM 的。于是开启了一天的阅读。首先花了一上午阅读“文件编码格式(转) - lionking - 博客园 ”这篇文章,阅读完后终于明白了“UTF-8 不是字符集”这句话。之后怕混淆再阅读了“字符集和字符编码(Charset&Encoding) - 博客 - 伯乐在线  ”确认。

 
这篇文章纯粹是用通俗的语言解释我以前混淆的几个概念,对于具体的规范不做解释,希望大家有像我一样疑惑的读完后不再疑惑,可以在需要时查阅正式的规范是解决需要的问题。
 
我们都清楚打开记事本看见一个字母 a ,它在磁盘上的二进制值是 0x61 。正是字符集让 0x61 显示成小写字母 a 。因此字符集和字符集中显示的字符是一一对应的。
我之前一直被“编码”这个词搞混了。因为在我们的日常交流或者看博客看书等都可以看见下面一些类似的话:
■“xxx 以 ASCII 编码显示为 yyy”。
■“该文件在 Windows 上以 ANSI 编码,在 Linux 下无法正常显示,需要在 Windows 上以 UTF-8 编码保存这样就可以在 Linux 下打开就不会乱码了”
■“UTF-8 不是字符集只是一种编码标准”。
这几句话给我造成了以下疑惑。
■“ASCII 和 ANSI 不是字符集么,怎么这里用来编码了”。
■“UTF-8 不是字符集,怎么可以用来编码呢?查查资料说采用 Unicode 字符集,Unicode 说是同一码,到底是个啥玩意?”。
 
首先,字符集(character encoding 或 character set)定义了二进制与字符的对应关系。通过字符集可以把字符转换成相应的二进制用于存储和传输,当需要阅读文字时,可以通过字符集把二进制转换成相应的字符。作为程序员我们都知道 ASCII 字符集(ASCII 码)是7位的,一共只能表示128个字符,具体内容,网上搜索都可以找到。
 
在继续往下写之前先在这里说明一下”什么是 ANSI 字符集,它和 ASCII 字符集有什么关联?“。
我最初见到提及”ANSI 字符集“的地方是在《Windows 程序设计》这本书中。书中前面就介绍 ANSI 字符集和 Unicode 字符集,可惜我当初看了几遍也没有看出个所以然,还有就是用 VC 写程序时,在”项目设置“有一项设置”字符集“,是个下拉框可以选择”ANSI 字符集“和”Unicode 字符集“。当时我也不知道到底是什么意思,反正只知道书中建议程序员多用 Unicode 程序集。所以我对于 ANSI 字符集和 Unicode 字符集的印象一直都是多用 Unicode 字符集。为什么说印象呢?因为我不知道具体是啥。
其实没有具体的某个字符集叫 ANSI 字符集,它只是在 Windows 上面的一个统称。ANSI 字符集应该来源于 ANSI 代码页(代码页其实就是字符集,只是早期的叫法而已)。因为 Windows 代码页最初是根据 ANSI 草案实现的,所以 Windows 代码页又叫做 ANSI 代码页。之后字符集这个词出现了,应该就把这些代码页叫做 ANSI 字符集了吧。在维基百科上面有关于代码页的介绍。ASCII 字符集是7位的,一共只能表示128个字符,表示其他语言就成了问题,后来对 ASCII 字符集进行了扩展,用两个字节表示其他语言,这样就绰绰有余了。比如简体中文 GB2312,繁体中文 big5,日语 SHIFT_JIS 。举个比较通俗(没有那么准确)的例子,在中国大陆的 Windows 电脑中 ANSI 字符集是指 GB2312 ,在中国台湾 Windows 电脑中 ANSI 字符集是指 big5,在日本 Windows 电脑中 ANSI 字符集是指 SHIFT_JIS 。就是这么个概念。这些字符集中每个字符都是以2字节编码,因此这种字符集又叫 DBCS 。
 
接着。以上我产生了两个疑惑。其实第一个疑惑完全是被表述误解。比如根据 ASCII 字符集把 0x61 显示为 a ,或者把 a 存储为 0x61 ,这句话也有人习惯表述为把 0x61 用 ASCII 编码为 a ,用 ASCII 把 a 解码为 0x61 。其实都是一个意思。因此关于编码这个词应该根据上下文语意来进行理解。
第二个疑惑是把 Unicode 字符集与 ASCII 字符集、ANSI 字符集和 GB2312 字符集搞混淆了。前面我们提到的 ANSI 字符集以2字节编码,比如在简体中文中 0x1234 是指某个字,到了繁体中文就成了另外一个字,到了日语又是一个日语字符。Unicode 是一个统称,当提到 Unicode 字符集其实是指 Universal Character Set, UCS 。我们可以说 Unicode 字符集,当然也可以说 UCS 字符集。UCS 字符集包括了其他所有语言的文字,比如拉丁语,简体中文,繁体中文,日语,韩语等。也就是说不同的语言中的不同字符在 UCS 中都一个唯一的位置,而不是像 ANSI 字符集那样,2字节在不同的地方表示不同的语言文字。这样 UCS 就实现了所有语言的大一统,当然 UCS 的字节数不止2字节,UCS 分为 UCS-2 和 UCS-4 ,分别表示占用2字节时表示的字符和占用4字节时占用的字符,在 UCS-2 前面加2个值为0的字节就变成了 UCS-4 。
我们明白了 Unicode 字符集,但是 Unicode 字符集在日常使用时并非直接使用字符对应的二进制,而是会对这个二进制再次编码后使用,或用于网络传输或用于磁盘保存。这种编码方法就叫做 UTF , Unicode Transformation Format 。
常见的 UTF 编码有 UTF-32,UTF-16,UTF-8 。UTF-8 由于特殊的算法是不需要额外声明字节序,但 UTF-32 或者 UTF-16 则不行,如果我们收到 UTF-16 字节流“594E”,不知道它的值是 0x594E 还是 0x4E59,这是”奎“还是 ”乙“?Unicode 规范中推荐的标记字节顺序的方法是 BOM ,Byte Order Mark。在UCS 编码中有一个叫做”ZERO WIDTH NO-BREAK SPACE“的字符,它的值是 0xFEFF,而 0xFEFF 在 UCS 中是不存在的字符。这样如果接收者收到 FEFF ,就表明这个字节流是 Big-Endian 的;如果收到 FFFE ,就表明这个字节流是 Little-Endian 的。UTF-8 不需要 BOM来表明字节顺序,但可以用 BOM 来表明编码方式。字符”ZERO WIDTH NO-BREAK SPACE“的UTF-8编码是 EF BB BF 。所以如果接收者收到以EF BB BF开头的字节流,就知道这是UTF-8编码了。
 
总结:
1)
ASCII 字符集是7位标识拉丁语的字符集。
Unicode 字符集就是指 UCS 字符集,它是统一定义了所有语言中的字符(目前绝大部分语言都有包括进去)。
ANSI 字符集是在 Windows 上面的一个统称,这些字符集是2字节编码,由 ASCII 字符集拓展而来。简体中文 GB2312 ,繁体中文 big5 都可以划分到这个范畴。
2)
代码页就是字符集。只是早期的叫法而已。
3)
UTF 是 Unicode 字符集的传输格式,这里传输是翻译成中文的叫法,可以在网络上传输也可以在磁盘上保存文件。UTF 本身不是字符集,是基于 Unicode 字符集。
 
引用:
1) 百度百科。ANSI 编码。http://baike.baidu.com/view/1273097.htm
2) 维基百科。Unicode。https://zh.wikipedia.org/wiki/Unicode
(注:维基百科中文已被墙!)

ASCII UNICODE UTF "口水文"的更多相关文章

  1. Unicode(UTF&UCS)深度历险

    Unicode(UTF&UCS)深度历险 计算机网络诞生后,大家慢慢地发现一个问题:一个字节放不下一个字符了!因为需要交流,本地化的文字需要能够被支持. 最初的字符集使用7bit来存储字符,因 ...

  2. 浅显总结ASCII Unicode UTF-8的区别

    如果觉得此地排版不好,欢迎访问我的博客 浅显总结ASCII Unicode UTF-8的区别 制作表单时,为了追求更好的用户交互体验,常常会有提示性的内容,比如提醒用户字符的限制.由于英文,中文字符的 ...

  3. 字符编码 ASCII,Unicode和UTF-8的关系

    转自:http://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/00143166410626 ...

  4. 字符编码 ASCII unicode UTF-8

    字符串也是一种数据类型,但是,字符串比较特殊的是还有一个编码问题. 因为计算机只能处理数字,如果要处理文本,就必须先把文本转换为数字才能处理.最早的计算机在设计时采用8个比特(bit)作为一个字节(b ...

  5. 字符集、字符编码、国际化、本地化简要总结(UNICODE/UTF/ASCII/GB2312/GBK/GB18030)

    PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 环境说明   普通的linux 和 普通的windows.    ...

  6. Unicode, UTF, ASCII, ANSI format differences

    Going down your list: "Unicode" isn't an encoding, although unfortunately, a lot of docume ...

  7. 【转】【编码】ANSI,ASCII,Unicode,UTF8之一

          不同的国家和地区制定了不同的标准,由此产生了 GB2312.GBK.GB18030.Big5.Shift_JIS 等各自的编码标准.这些使用多个字节来代表一个字符的各种汉字延伸编码方式,称 ...

  8. 码表 ASCII Unicode GBK UTF-8

    2017-1-3 [ASCII]一个字节(7位,128个字符,2个16进制) 不包含中文 ASCII(American Standard Code for Information Interchang ...

  9. ASCII, Unicode, UTF-8, 8进制, 16进制等各种编码学习理解笔记

    字符编码的发展历史 Unicode和UTF-8有何区别? 在这个问题下的于洋的最高票回答中,比较完整地介绍了字符编码的发展历史,为了便于记忆,再次简要概括一番. 一个字节:最初一个字节的标准是混乱的, ...

随机推荐

  1. css样式控制元素固定在底部

    回复固定在底部:css样式用到了 box-sizing属性 box-sizing:border-box; -moz-box-sizing:border-box; /* Firefox */ -webk ...

  2. JavaScript 文件操作方法详解

    可以通过浏览器在访问者的硬盘上创建文件,因为我开始试了一下真的可以,不信你把下面这段代码COPY到一个HTML文件当中再运行一下! <script language="JavaScri ...

  3. vue-bus 组件通信插件

    vue-bus 一个 Vue.js 事件中心插件,同时支持 Vue 1.0 和 2.0 原因 Vue 2.0 重新梳理了事件系统,因为基于组件树结构的事件流方式实在是让人难以理解,并且在组件结构扩展的 ...

  4. MVC项目总结

    View命名 View下有多个模块的文件夹,我们根据微软的规定,每个模块下的首页都为Index.cshtml命名 获得当前页面的控制器名称 var currentControllerName = th ...

  5. jsp获取web.xml 里的配置项

    ServletContext servletContext = request.getSession().getServletContext();                String titl ...

  6. 关于 php 调用 其他语言写的Web Service SOAP 接口的参数传递问题

    关于 php 调用 其他语言写的Web Service SOAP 接口的参数传递问题,有需要的朋友可以参考下. php调用java写的soap接口经验:   场景一: java是以数组的形式接收参数的 ...

  7. (个人开源)ffpanel --ffmpeg的GUI,让ffmpeg离开黑黑的命令行

    程序及源代码下载地址 :https://github.com/langsim/ffpanel

  8. Mysql 5.7.18 加密连接mysql_ssl_rsa_setup

    MySQL 5.7.18 下载地址: https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.18-linux-glibc2.5-x86_64. ...

  9. Can a GridView have a footer and header just like ListView?

    Aquick question: In ListView I use this code: list.addHeaderView(headerView); How to deal with it wh ...

  10. nagios-plugins安装报错--with-mysql: no

    --with-mysql: no 解决方法 yum安装mysql-devel yum install mysql-devel