是时候了解关于字符集编码了!!!
ASCII#
最早计算机刚出世时,只有一ASCII编码方式, American Strand Code For Information Interchange
, ASCII 使用7位 标识一个字符, 对于只认识 0 1 的计算机来说, ASCII 可以记录 2^7 个字符, 针对欧美国家来说, abc... 再加上一些运算符号 ,ASCII足够用了
但是问题来了,不光是美国,像法国等国家也普及计算机,很快ASCII就不够了
ISO-8859-1#
于是 ISO-8859 出现了, 它使用8 位 表示一个字符, 而且完全兼容ASCII编码表
ISO-8859-1相对于ASCII有两个优点:
- ISO-8859-1 可以表示 2^8个字符, 对ASCII
- ISO-8859-1 使用8位表示一个字符, 这使得他可以完全使用每个字节的每一位
然后这还是仅仅对西欧国家而言, 后来计算机普及到了亚洲
gb2312#
对我们国家来说,我们同样需要一种编码表,让计算机认识我们的汉字,于是 中华人民共和国 指定了gb2312 , 国标2312 , 它使用两个字节表示一个汉字, 容纳了几千个常用的汉字
但是问题并没有打住,gb2312 并没有包含极少数的生僻字
gbk#
gbk编码表弥补了 gb2312并不包含极少数的生僻字的现状
然而,gbk依然不能表示全部的中国文字
于是:
gb18030#
gb18030 的扩展,使他成为了最完整的汉字的编码集
但是, 这却仅仅是对大陆而言
Big5#
我们的宝岛台湾仍然使用 繁体字, 他们的编码表是 big5
随着计算机的全球化,于是国际标准化组织出现了,他们想统一世界上的编码方式
unicode#
国际标准化组织对全世界的编码方式进行了汇总, unicode 理论上是可以表示世界上全部的符号的, 它统一使用两个字节表示一个字符, 算算看,他可以表示 256^256个字符
现在unnicode的出现,不再担心不能表示全所有的字符了,但是问题又来了,对于原来的欧美国家来说, 本来一个ISO-8859-1 就够他们使用的,结果来个unicode, 缓存容量急剧上升,这是个不好的事情, 于是主角来了
UTF(Unicode translation format)#
UTF 有三个分支, UTF-8 UTF-16 UTF-32;
其中UTF-8 使用的变长的字节表示 , 也就是说,假如是当前的字符是a, 它会使用一个字节表示, 假如是汉字,他使用三个字节表示 .
UTF-16 和 unicode 一样的都是使用两个字节
UTF和Unicode的关系 Unicode是一种编码方式,而utf是一种存储格式
比如说我们的文件是utf-8这种存储格式的, 即传进去的数据都是用utf-8
磁盘上文件都是有自己的存储格式的, 比如常用的文本文件的存储格式都是utf-8
如下图:我们想实现 数据从源文件拷贝到目标文件
{% asset_img 1.jpg image %}
假如源文件的存储方式是utf-8, 但是我们使用ISO-8859-1对它进行解码, ISO-8859-1碰到一个字节就认为他是一个字符,这显然和utf-8的动态编码相冲突, 因此我们解码得到的结果无异于全是乱码
紧接着,我们使用ISO-8859-1对得到的乱码,进行编码,同样对于ISO-8859-1来说,他是认识这些乱码的,而且ISO-8859-1并没有和utf-8一样充分了利用了每一个字节的每一位,于是它把他们按位编码会数据原始的状态
在然后,我们把编码后的数据写到 用uft-8存储的目标文件,对于目标文件来说,得到的数据就是源文件中编码形态 故不会出现乱码
如果我们想用 utf-16类型的编码器,对 utf-8类型的文件进行编解码呢?
结果要么会报错,要么就行出异常MalformedInputException
一个难看的参数
试想,如果utf-8存储格式的文件中, 只有一个数据 1, 他就是1字节, 而utf-16默认是两个字节, 编码后的结果也全部是FEFF0031这样的, 对于utf-16来说,他是无法对1进行解码的,直接会报错
源文件和目标文件的 存储格式也要相同,这决定了他们对数据字节的划分不同,得到的结果自然不同