最近接了一个单是需要把非 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. Java函数的基本知识

    http://blog.csdn.net/cxwen78/article/details/7322891主要从Java函数的定义,函数的特点,函数的应用,函数的重载四个方面来讲解Java函数. 一.函 ...

  2. Web Service之Soap请求响应内容中文编码解密

    java模拟Soap请求测试Web Service接口,发现Web Service响应内容中的中文竟然是编码格式.比如: 中文:退保成功 Soap中文编码:退保成功   我仔细分析后发现,退编码实际上 ...

  3. Source Insight 4.0 破解和使用

    参考出处: https://blog.csdn.net/u011604775/article/details/81698062 https://blog.csdn.net/user11223344ab ...

  4. 图片压缩CompressUtil解析

    CompressUtil 流程图: CompressUtil 类 具体解释 public class CompressUtil { /** * 终于封装的压缩方法 * @param imgPath * ...

  5. 线性表的链式实现(C++)

    相关内容: 线性表的顺序实现 链式实现(C语言) (推荐在GitHub上查看,下面代码只是最初实现,后续如果有修改,由于太麻烦,不会再更改下文,仅仅更新Github上的代码文件) 结点以及链表类的定义 ...

  6. [转]FPGA网站推荐

    1. OPENCORES.ORG这里提供非常多,非常好的PLD了内核,8051内核就可以在里面找到.进入后,选择project或者由http//www.opencores.org/browse.cgi ...

  7. Spring IOC源码分析之-刷新前的准备工作

    目录 ClassPathXmlApplicationContext的注册方式 加载父子容器 配置路径解析 容器刷新 刷新容器之刷新预处理 ClassPathXmlApplicationContext的 ...

  8. js判断参数类型

    如何判断js中的数据类型:typeof.instanceof. constructor. prototype方法比较 如何判断js中的类型呢,先举几个例子: var a = "iamstri ...

  9. 【Unity3D】【NGUI】Atlas的动态创建

    NGUI版本号:3.6.5 1.參见SZUIAtlasMakerRuntimeTest设置对应的值以上值须要提前设置好 2.没有检查是否atlas可以正确创建,自己可以改,增加返回值 3.代码都是在N ...

  10. hibernate QBC查询

    HQL运算符 QBC运算符 含义 = Restrictions.eq() 等于equal <>  Restrictions.ne() 不等于not equal >  Restrict ...