修改
Windows 记事本的 ANSI、Unicode、UTF-8 这三种编码模式有什么区别?修改
Windows 的记事本默认存储文本文档编码是 ANSI,想问一下为了最大跨平台兼容性,应该采用哪种编码格式比较好?修改
11 个回答
梁海,U+6211, U+7231, U+5B83
炎森、白玉汤、Stanley等人赞同
简答。一些细节暂无精力查证,如果说错了还请指出。
一句话建议:涉及兼容性考量时,不要用记事本,用专业的文本编辑器保存为不带 BOM 的 UTF-8。
* * *
如果是为了跨平台兼容性,只需要知道,在 Windows 记事本的语境中:
- 所谓的「ANSI」指的是对应当前系统 locale 的遗留(legacy)编码。[1]
- 所谓的「Unicode」指的是带有 BOM 的小端序 UTF-16。[2]
- 所谓的「UTF-8」指的是带 BOM 的 UTF-8。[3]
GBK 等遗留编码最麻烦,所以除非你知道自己在干什么否则不要再用了。
UTF-16 理论上其实很好,字节序也标明了,但 UTF-16 毕竟不常用。
UTF-8 本来是兼容性最好的编码但 Windows 偏要加 BOM 于是经常出问题。
所以,跨平台兼容性最好的其实就是不用记事本。
建议用 Notepad++ 等正常的专业文本编辑器保存为不带 BOM 的 UTF-8。
另外,如果文本中所有字符都在 ASCII 范围内,那么其实,记事本保存的所谓的「ANSI」文件,和 ASCII 或无 BOM 的 UTF-8 是一样的。
* * *
阮一峰那篇〈字符编码笔记:ASCII,Unicode和UTF-8〉的确很有名,但从那篇文章能看出来他其实还是没完全搞清楚 Unicode 和 UTF-8 的关系。他依旧被 Windows 的混乱措词误导。事实上,几年前我读完他那篇文章之后依旧一头雾水,最终还是自己看维基百科看明白的。
所以,那篇文章不值得推荐。
* * *
关于字符集(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」来称呼一个编码方案不合适,并且误导。
* * *
[1] Windows 里说的「ANSI」其实是 Windows code pages,这个模式根据当前 locale 选定具体的编码,比如简中 locale 下是 GBK。把自己这些 code page 称作「ANSI」是 Windows 的臭毛病。在 ASCII 范围内它们应该是和 ASCII 一致的。
[2] 把带有 BOM 的小端序 UTF-16 称作「Unicode」也是 Windows 的臭毛病。Windows 从 Windows 2000 开始就已经支持 surrogate pair 了,所以已经是 UTF-16 了,「UCS-2」这个说法已经不合适了。UCS-2 只能编码 BMP 范围内的字符,从 1996 年起就在 Unicode/ISO 标准中被 UTF-16 取代了(UTF-16 通过蛋疼的 surrogate pair 来编码超出 BMP 的字符)。都十多年了,求求大家别再误称了……
[3] 把带 BOM 的 UTF-8 称作「UTF-8」又是 Windows 的臭毛病。如果忽略 BOM,那么在 ASCII 范围内与 ASCII 一致。另请参见:「带 BOM 的 UTF-8」和「无 BOM 的 UTF-8」有什么区别?http://www.zhihu.com/question/20167122
编辑于 2013-01-2945 条评论
时国怀,真是太糟糕了
三二一、阎帅、ther lu等人赞同
先来解释一下这三种编码的历史吧:
ANSI:最早的时候计算机ASCII码只能表示256个符号(含控制符号),这个字符集表示英文字母足够,其中,我们键盘上可见的符号的编码范围是从32到126(大小写英文字母、数字、英文符号等)。但表示汉字、日语、韩语就不太够用了,汉字常用字有3000多个。
但是中国人也要用电脑打字,于是,中国人就研究出来了最早的中文字符集GB2312(GBK就是后来的扩展),GB2312的做法是,把ASC码取值范围的128~255这个区间挪用了一下,用两个ASC码表示一个汉字,这样可用的编码范围用十六进制表示就是0x8080到0xFFFF,这大概能表示一万多个符号,足够了。[注:实际没用那么多,GBK的范围是8140-FEFE]
那个时候,计算机技术还不发达,各个国家搞自己的,比如台湾,也另搞了一套,叫BIG5(俗称:大五码),跟大陆的也不太一样,但方法是类似的,都是用0x80到0xFF这个区间。
然后日语(有编码JIS)、韩语等等也各搞一套。
这些国家的编码区间都是重叠的,但同一个汉字(比如有一些汉字同时存在于简体、繁体、日语汉字中)有不同的编码,很混乱是不是?但也凑合用了。编码不同导致了很多麻烦,比如一个网页,如果你不知道它是什么编码的,那么你可能很难确定它显示的是什么,一个字符可能是大陆简体/台湾繁体/日本汉字,但又完全是不同的几个字。
所以如果用一些很老的软件,可能会听说有中文版/日文版之类的,对应的版本只能在对应的系统上运行。
后来,这个对操作系统的开发实在是太困难了,因为这意味着不同语言的版本,都要重新编码。于是发明了Unicode。
Unicode这个东西,就是要把地球上所有的语言的符号,都用统一的字符集来表示,一个编码真正做到了唯一。
Unicode里有几种方式:
UTF-16BE/LE:UTF-16就是Windows模式的编码模式(Windows里说的Unicode一般都是指这种编码),用2个字节表示任意字符,注意:英文字符也占2个字节(变态不?),这种编码可以表示65536个字符,至于LE和BE,就是一个数值在内存/磁盘上的保存方式,比如一个编码0x8182,在磁盘上应该是0x81 0x82呢?还是0x82 0x81呢?就是高位是最先保存还是最后保存的问题,前者为BE,后者为LE。
UTF-8:UTF-8则是网页比较流行的一种格式:用一个字节表示英文字符,用3个字节表示汉字,准确的说,UTF-8是用二进制编码的前缀,如果某个UTF-8的编码的第一个字节的最高二进制位是0,则这个编码占1字节,如果是110,则占2字节,如果是1110,则占3字节……
好了,说了这么,再来研究Windows的记事本。
Windows早期(至少是95年以前的事情了)是ANSI字符集的,也就是说一个中文文本,在Windows简体中文版显示的是中文,到Windows日文版显示的就不知道是什么东西了。
后来,Windows支持了Unicode,但当时大部分软件都是用ANSI编码的,unicode还不流行,怎么办?Windows想了个办法,就是允许一个默认语言编码,就是当遇到一个字符串,不是unicode的时候,就用默认语言编码解释。(在区域和语言选项里可以改默认语言)
这个默认语言,在不同Windows语言版本里是不同的,在简体中文版里,是GBK,在繁体中文版里,是BIG5,在日文版里是JIS
而记事本的ANSI编码,就是这种默认编码,所以,一个中文文本,用ANSI编码保存,在中文版里编码是GBK模式保存的时候,到繁体中文版里,用BIG5读取,就全乱套了。
记事本也不甘心这样,所以它要支持Unicode,但是有一个问题,一段二进制编码,如何确定它是GBK还是BIG5还是UTF-16/UTF-8?记事本的做法是在TXT文件的最前面保存一个标签,如果记事本打开一个TXT,发现这个标签,就说明是unicode。标签叫BOM,如果是0xFF 0xFE,是UTF16LE,如果是0xFE 0xFF则UTF16BE,如果是0xEF 0xBB 0xBF,则是UTF-8。如果没有这三个东西,那么就是ANSI,使用操作系统的默认语言编码来解释。
Unicode的好处就是,不论你的TXT放到什么语言版本的Windows上,都能正常显示。而ANSI编码则不能。(UTF-8的好处是在网络环境下,比较节约流量,毕竟网络里英文的数据还是最多的)
举例:
同样一段中文文本(可以插入一些英文),保存成ANSI/Unicode/UTF-8,三个文件。
修改windows的默认语言为日语之类的(WIN7的改法是:控制面板-时钟、语言和区域-更改显示语言-区域和语言-管理-非unicode程序语言-更改区域设置/WNIXP改法是:控制面板-区域和语言选项-非unicode程序语言)。
修改完要求重启,重启以后,再打开这三个文件,ANSI的编码全乱了,其余两个都正常显示,这就是UNICODE的作用。
另外,为什么记事本、开始菜单什么的还是正确的中文呢?明明我已经改了默认语言了?因为它们的程序编码也是unicode的。
要把txt发给国外的朋友或者用在非中文的操作系统/软件里,那么你的编码最好选择unicode
-完-
编辑于 2012-12-2013 条评论
陈甫鸼,生长于闽,求学入秦,漂泊适燕,实秦人也。
徐翔宇、刘中阳、北岛游鱼等人赞同
谢谢 @梁海 邀请。最近状态不佳,耽误了这么久,对不起。
其实前面他自己的回答已经很完善了。我补充一些细节就可以。
ANSI 确实是遗留编码,在不同语言的系统中编码不同,这一部分在微软的术语中叫 code page。比如所谓 GBK 编码,实际上更多地被叫做 CP936。这个术语是从 IBM 早期的一些工作中继承下来的,现在也没改变。但是,代码页这个概念在引入更大的字符集时已经遇到了问题,比如当初 GBK 扩展到 GB18030 时,它无法自然地用同一个代码页解决问题,不得不使用非常复杂的映射技术在几个代码页中切换才最终达到目的。
所谓微软的 Unicode,确实是 UTF-16LE。这个问题上 MSDN 文档在术语运用上有很多前后矛盾的地方,所以很多程序员都不太了解。再加上微软 SDK 默认的 WCHAR 是两个字节,进一步加剧了混乱程度。事实上时至今日,微软的默认编码不一定是两字节了,因为 Unicode 早已超过了 65536 个字符。
如果是为了跨平台,那么最有效的办法确实是坚持使用 UTF-8。不过是否使用 BOM 则未必真的需要很纠结。事实上现代的编辑器都可以很好地处理 BOM,比如 VIM。在 UNIX 环境下不适合使用 BOM 的场合有两个:一个是 XML,另一个是老旧的 shell 脚本。前者是因为规范里就没有 BOM 的位置,而后者则是因为历史原因而不能很好支持。而更大范围内的应用,比如 Python 脚本,则可以很好地处理 BOM。
发布于 2012-12-1413 条评论
阿哲,人生苦短、IT工程师
ASCII是古老的编码,那个时候还不区分字符集和编码,基本可以看作合二为一的东西。
Unicode严格来说是字符集,可以有多种编码。
UTF-8是一种Unicode的编码。
兼容性最好的,我记得好像是UTF-8不带BOM头。
注: 字符集(char set)就是字符的集合,收录了一定数量的字符。每个字符有对应的ID值,叫码点(code point)。实际存储的时候,不一定是直接存储字符串的码点(比如,为了节约空间),要进行转换。这个转换规则就是编码。
发布于 2015-02-14添加评论
vczh,专业造轮子https://github.com/vczh-libraries
曾叶、陈立、乙醚等人赞同
Unicode是FFFE后面接着UTF-16字符串的二进制文件,UTF-8是EFBBBF后面接着UTF-8字符串的二进制文件、ANSI是有时候会被解释为当前locale对应的code page的字符串的二进制文件。
他们都是二进制文件,不要有太多幻想。
发布于 2014-07-175 条评论
匿名用户
王重阳、左昊诚、王宇赞同
阮一峰解释得不错:http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html
1)ANSI是默认的编码方式。对于英文文件是ASCII编码,对于简体中文文件是GB2312编码(只针对Windows简体中文版,如果是繁体中文版会采用Big5码)。
2)Unicode编码指的是UCS-2编码方式,即直接用两个字节存入字符的Unicode码。这个选项用的little endian格式。
3)Unicode big endian编码与上一个选项相对应。我在下一节会解释little endian和big endian的涵义。
4)UTF-8编码,也就是上一节谈到的编码方法。
发布于 2012-12-121 条评论
韩曙,写程序算数据
马志宇、jtuki赞同
基本的问题是:非英语字符需要扩展 只面向英文的ASCii编码。
ANSI:泛指最早每种国家语言各自实现的编码方式,各个编码互相之间不兼容,比较省空间。
Unicode:一套抽象的兼容所有常用语言的编码方式,但是不适合计算机系统直接存储。
UTF-8:一种将unicode转换成适合计算机存储的方式,
相对其他的UTF-xx省空间,同时又可以和ASCII混用,结构相对复杂,底层处理相对慢。
UTF-16,UTF-32:另外的unicode存储编码,结构简单,不能和ASCII混用。
BOM:一种为了跨平台设计的文件起始标记,但很多程序没去处理这个,用了BOM反而常造成问题。
发布于 2012-12-202 条评论
蓝恒,图农
windows系统中ANSI一般指在地化的字符集及其编码方式,根据系统版本及相关语言选项而有所不同,&H7F以内采用ASCII编码,在简中环境一般还包括GB2312及后来的GBK、GB18030编码(这三个为字符集,但通常也隐含EUC-CN编码的含义),利用的是ASCII扩展编码空间,即所谓制表符(该空间也包含拉丁、希腊字母等非英文字符),因此包含有表格字符的文本在简中环境下,表格部分常常会被显示成汉字。实际上狭义的ANSI编码应该就是所谓ASCII及其扩展码部分,记事本等地方出现的ANSI是极不严谨的。
Unicode是国际标准的字符集,在windows中常常也特指UTF-16(el小头)编码,每个字符占俩字节。UTF-8则字符所占长度为变长。
实际上windows及微软其他软件中,很多表述不是特别严谨,比如ASC()函数,该函数原本指取首字符的ASCII码值,而描述中是取首字符的ANSI码值,但在VB中参量为中文字符的时候和在老版本BASIC中返回的结果却大不同,老版本为&H80到&HFF之间,而VB中返回的却为UTF-16码值。
就兼容及经济性来讲,不同的环境这几种编码各有优缺点。兼容性来说其实对我来说差不多,只要尽量使用同一种编码就不会对我产生困扰,具体还要考虑到所用到的软件环境兼容哪一种。而经济性么,源代码、网页代码之类的东西用utf-8看起来比较经济,但对于中文为主的文本性的内容而言(例如文学作品等),双字节的UTF-16更省,而且个人感觉UTF16的文件很整齐,计数和查找比较方便。“ANSI”则对较老的环境兼容性很好,也不存在BOM,在不涉及复杂多语言环境的情况下也是个不错的选择。
发布于 2015-02-20添加评论
Frank Van,最近喜番上了贝儿
ansi比较好 他是适应你操作系统语言的编码格式
发布于 2014-07-18添加评论
白玉汤,程序员
谢谢啊谢谢啊!!我正在遭遇这个困惑
发布于 2015-04-02添加评论
蓝色鼓点,创业者,壁球爱好者,App及嵌入式软件开发,…
张帅、刘传君赞同
以上解释都或多或少问题。关于宽字节编码,跨平台的(windows/Linux/MacOS X 开发者最有体会,加上我因为开发电子书程序,系统的研究和测试了开源字符串转换库iconv库这个东西,这个问题应该是比较了解。我写过一个比较长的分析文章。具体请看http://blog.chinaunix.net/uid-20587912-id-405017.html 《汉字编码与Linux中文处理》 .近来偏向Mac OS X下开发居多,因此深有体会。
这里简单总结一下:
1.ANSI 就是ASCII编码。一个英文字符占一个字符
2.GB2312 是国内利用ASCII控制字符(即码值超过127)的两个字符形成一个汉字的原理。在DOS时代和windows 3.1时代用的就是这个方案,必须要外挂系统来解决显示问题。 同时代台湾搞一个BIG5编码也是相同原理,但是码值有冲突,所以那个时代txt 乱码是很头痛问题。 一个汉字相当于两个字符。但是这个格式用得还是很多。网上txt 中文小说几乎都是这个格式,还有歌词文件 lrc也是这个格式。后来为兼容繁体字,后推出一个GBK 大字集。
3. 国标组织为了解决世界各国的宽字符编码不统一的问题,搞出一UNICODE编码。把世界常用的语言的字符编一编码采用两个字符。世界约有几万字符(主要中文吃了一片),因此不同国家用不同代码区(code page 区别)(无论英文,汉字,泰文等)均是如此。 windows是内核采用了UNICODE编码。 但是在应用程序这一级为了兼容老的程序还有一套API,留给原来的应用程序来用。
4.到了Linux 和Mac OS X, 内核的编码采用是UTF-8,宽字符如汉字,采用的UTF-8编码。这个主要是针对网络传输的,从名字就可以看出来,UCS Transfer For .这个编码的特点除了统一编码外,还有的码值是变长,即一个字符可以由1-4字符表示,英文就与ASCII对应,汉字最短是两个字符,最长是四个字符,这个可以把传输字符量减到最小。
UTF8 与UNICODE没有规律的转换关系,两者编码是有冲突的。
——————————————–
跨平台开发者要碰到一些问题: 在windows写的汉字,比如在程序中汉字注释(无论是UNICODE,还是GB2312)在LINUX下UTF8显示均是乱码。反过来也是一样。
当然有一些windows工具如UltraEdit 能直接识别,那是应用程序自己作了转换。
至于说哪种格式通用,没有定例,完全看应用程序的要求。我举几个常见例子。
1. 歌词文件 lrc,从我看的研究来看,哪个平台都是采用ANSI + GBK编码的。你随便从QQ音乐下载几个歌词就知道了。现在从网上下的小说txt ,基于是GBK格式的。
2.java内码指定是UNICODE编码,所以你在哪一个平台的Eclipse里输入的汉字均采用UNICODE编码,这样在Mac OS X 你可以发现在Eclipse写的汉字,用XCode 打开就乱码。
3. XML这一些格式,里面要求是UTF-8,你可以看第一句就注明是UTF-8格式。
相关问题
- 有没有方法能将 Windows 中设置进程内 ANSI 系列 API 的默认编码换成 UTF-8 编码?2 个回答
- Windows为什么用GBK而不是UTF-8?11 个回答
- 如何让一个完全不懂电脑的 Windows XP 用户成功打开 UTF-8 编码的富文本文档?5 个回答
- GB 2312、GBK 和 UTF-8 编码下,汉字字节的取值范围都是什么?1 个回答
- 「带 BOM 的 UTF-8」和「无 BOM 的 UTF-8」有什么区别?网页代码一般使用哪个?
http://www.zhihu.com/question/20650946