编程技术记录

世界你好!

我曾经以为理所当然应该知道的事,而如今的一些程序员却一脸茫然。

先声明,我本人对Java没有偏见。

起因是这样的,同事拿着一段Java代码给我看,咨询下啥啥功能的事。我便细细观摩,看到关于读写文件的代码–将文件以字符串形式读到内存中。

看了会儿,我说:“这块有点瑕疵,没有指定文本的编码格式”
他说:“什么编码?以前也这么写的,运行起来没有问题。”
……(后续交流省略)…..

从我近年来和多位从事移动开发的程序员接触来看,我的感触就是移动互联网发展太快了,以至于他们完美的错过了这个行业很基础的知识灌溉—-或者忙着写业务了,或者手中正翻看xx天速成、包教包会的书,或者忙着追各种吹牛x的黑科技了,

好了,抱怨了一通,我转回正题。为什么要指定文本的编码格式?这事儿要从上世纪的蛮荒时代说起。

百花齐放

我们都知道,计算机的中储存以字节(8比特)为单位,人们阅读的文本在计算机存储都是一堆字节,而不是什么“世界你好,hello world”之类的可阅读文本。

为了解码这些字节,必须按照一定的规范将文本映射为计算机可以储存的字节。最早的可知晓的规范就是非常著名的ASCII编码,比如 0x30 代表字符0, 0x41 代表字符A等等

ASCII编码,全称为美国信息交换标准代码, 在1967年作为规范标准发布,主要用来表示现代英文的编码约定(可以理解,那时计算机的主导是美国,到现在美国也是引领者),只定义了128个字符。

随着计算机的发展,越来越多的国家和地区使用计算机,自然因为语言不同,也有了制定适合自己国家和地区的文本编码了,诸如ISO系列,ibm系列,Windows系列,像中文的big-5,gb系列等,详细请参考

这里,闲聊一句,上世纪80、90年代BP寻呼机,支持汉显和不支持汉显的价格有时能差一倍。

当编码多了,最大的问题是不同编码之间无法相互兼容,只有程序员能明白这其中的苦楚;若还是不明白,问问微软在上世纪是如何在各个国家和地区适配多语言的。

Unicode一统

文本编码不能相互兼容,这为软件行业的发展、互联网的推广带来了很大的麻烦,统一字符编码势在必行。最终统一的结果也就是今天大家看到的Unicode—是由一个名为 Unicode 学术学会(Unicode Consortium)的机构制订的字符编码系统,支持现今世界各种不同语言的书面文本的交换、处理及显示。该编码于1990年开始研发,1994年正式公布,最新版本是2019年5月7日的Unicode 12.1.0(这段摘自百度百科)。

字符集和编码

这里单独说下字符集和编码的关系。
平时我们交流时,很少说字符集,通常都是Unicode编码、GB2312编码,UTF8之类的。

严谨的来说,包括Unicode、ASCII、GB2312在内的编码规范,其实分为两部分:字符集、编码方式。

字符集,指的是该规范收录了哪些字符,可以称之为字符的集合。例如,ASCII收录了数字、大小写英文字母、一些常用的符号和一些控制打印的字符;GBK2312收录包括ASCII在内的符号,以及常用的汉字和符号,还收录了包括拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母在内的682个全角字符。

编码方式,指将收录的字符如何映射到计算机中的字节存储。简单来说,ASCII是单字节编码,为每一个收录的字符分配一个字节的数值表示,比如 0x30 代表字符0, 0x41 代表字符A

GBK2312是双字节编码,为每一个收录的字符分配两个字节的数值表示。

UTF8,是Unicode字符集的一种编码方式,变长字节;
UTF16,是Unicode字符集的一种编码方式,两个字节(不考虑Java中的字符代理对情况);另外,考虑到网络传输,UTF16还要区分大小端(大小尾)。两个数字 0xFFFE,0xFEFF,估计还是有人能看懂的。
UTF32,是Unicode字符集的一种编码方式,四个字节;
UTF7,有谁听说过吗?是Unicode字符集的一种编码方式,变长字节。

另外,强烈建议在大部分场景使用UTF8编码方式,这是真正的万国编码。

为什么要指定文本编码

答:因为鬼知道我不指定编码,软件会怎么解码文本?

联通为什么干不过移动

答:微软记事本告诉你https://www.iteye.com/blog/mfkvfn-1703414

在windows操作系统中,新建一个文本文件,用词本打开,输入"联通"两个字之后,保存,关闭,然后再次打开,你会发现这两个字已经消失了,代之的是个乱码!而输入移去就不会有问题。

  据说这就是联通之所以拼不过移动的原因。

  Windows NT(Windows 2000及以上)版本的记事本 ,亦默认安装于Windows 2000和Windows XP中,可以侦查到缺乏字节序标记的Unicode文件。这个功能由一个Windows API提供,名为IsTextUnicode() 。但是,这个功能是不完美的,副作用是一些小写字体的ASCII文字,会错误判断为UTF-16。

  在2006年5月18日,有报道称,对于一个含有类似"this app can break"这样短语的文档(甚至是类似"aaaa aaa aaa aaaaa"的简单短语),记事本会将其打开并显示为Unicode二进制文本。如果安装了相关中文字体则会显示二进制码所对应的汉字。造成这个错误的字符串可能形如“4个字母+空格+3个字母+空格+3个字母+空格+5个字母 ”,或者“4个字母+空格+5个字母+空格+5个字母+空格+5个字母 ”,并且文档末尾没有换行符。有人认为这是一个复活节彩蛋 ,但事实并非如此。还有人认为这是由于记事本的Unicode的检测算法所引起。

  这个问题已在Windows Vista版本的Notepad中被修复。

  但是,记事本还有一个问题,就是用ANSI保存的文档有时会被误认为Unicode。如在记事本中输入“联通 ”并保存,再次打开的时候会显示乱码,目前尚未被修复。

发表回复

© Beli. All Rights Reserved.