字符编码种类有多少种?
摘要:前言 曾经在一场面试中,问到过UTF-8与UTF-16的区别,我一脸懵逼,惨遭羞辱。 最近在使用rider这个IDE的过程中,发现在visual studio中好好的代码,在rider中是乱码。 故此深入了解一下字符编码的前世今生。 前世:
前言
曾经在一场面试中,问到过UTF-8与UTF-16的区别,我一脸懵逼,惨遭羞辱。
最近在使用rider这个IDE的过程中,发现在visual studio中好好的代码,在rider中是乱码。
故此深入了解一下字符编码的前世今生。
前世:编码的蛮荒时代
由于计算机只能存储0/1二进制数据,因此计算机字符编码的起点,本质是为了解决字符与二进制数据的映射问题。
ASCII
计算机诞生于美国,因此最早的编码需求仅针对英文字符。1967年发布的ASCII(American Standard Code for Information Interchange)成为第一个通用编码:
特点
使用一个字节(8位)中的低7位来表示字符,因此可以表示2^7=128个字符。
其内容主要包括,英语字母的大小写,数字0-9,标点符号,以及一些控制字符(换行\n,回车\r等符号)。
优点
简单,高效,仅占1个字节,完全满足英文场景下的计算机使用需求,成为计算机编码的底层基石。
缺点
只能表示英语字符,对于其它语言捉襟见肘。
眼见为实
var originalString = "C#编程";
Console.WriteLine($"originalString = {originalString}");
//ASCII编码
try
{
var asciiBytes=Encoding.ASCII.GetBytes(originalString);
Console.WriteLine($"ASCII 编码 (字节数: {asciiBytes.Length}):");
Console.WriteLine($" 字节: {BitConverter.ToString(asciiBytes)}");
Console.WriteLine($" 解码回字符串: \"{Encoding.ASCII.GetString(asciiBytes)}\"");
}
catch (Exception)
{
Console.WriteLine("ASCII 解码失败");
}
可以看到,对于英文字符C,与特殊符号# 。 ASCII能够正常编码解码,但对中文就无能为力了。
拓展ASCII与多字节字符(MBCS)
鉴于ASCII的缺点,各国为了能在计算机中表示自己的语言,开始制定自己的编码标准。
同样是英文语系的西欧语言,选择利用ASCII的最高位,将编码范围拓展到2^8=256个,比如ISO 8859-1。
特点
前128位与ASCII完全一致,拓展了后128位。补充了西欧重音字符以及特殊符号
缺点
仅覆盖西欧,对亚洲,非洲,俄文依旧不支持。
由于ASCII与ISO-8859-1无法满足多语言需求,各国纷纷开始定制专属的本地化编码,只为适配本国文字,毫无兼容性可言,因此开始了编码最混乱的时代。
像中文这样拥有成千上万字符的语言,靠拓展ASCII是远远不够的,一个字节最多表示256个字符,所以人们发明了多个字节来表示一个字符的方法。
GB2312
作为中国的国家标准,GB2312大约收录了6763个常用汉字,后续推出的GBK作为其超集(支持1-2字节编码,覆盖更多生僻汉字和符号),GB18030则进一步扩展为1-4字节编码,兼容GBK并覆盖全球所有字符。
BIG5
中国台湾/香港地区使用的繁体中文编码标准
Shift_JIS
日本使用的编码标准
这个时候的核心问题在于,大多数国家和地区都各自为政,互不兼容。比如一个GBK编码的文件,在使用Big5编码的程序中打开,就会显示为乱码。
编码之间的混乱,导致了软件开发,数据交互的国际化几乎是不可能的。
