【基础/笔记】编码

  • 编码
    信息从一种形式或格式转换为另一种形式的过程也称为计算机编程语言的代码简称编码
    比较早期的编码如摩尔斯电码和布莱叶盲文,它们都通过这种编码方式解决了人类所遇到的巨大难题。

  • 字节(byte)与字符
    字符指的是我们生活常用的文字或符号,文字在人类发展过程中已经有几千年历史,是人类比较容易理解的一种信息表示方式。
    为了使数字转化为字符,就需要使字符(包括数字)与数字编码对应,这样一个系统叫字符编码集,每一个编码叫作字符编码
    数字计算机存储器按位存储,位来表示数和机器码,但使用多少位来表示一个字符呢。

  • ASCII码
    后来在发展过程中有了美国信息交换标准代码,简写为ASCII码,技术按7位编码但使用8位值来存储的,也就是一个字节。
    一个字节占8个二进制位(bit),可表示十进制的0~255,用16进制表示则是00~FF。
    ASCII 码一共规定了128个字符的编码,只占用了一个字节的后面7位,最前面的一位统一规定为0。
    操作系统使用了ASCII标准来处理字符信息,我们通过使用键盘输入信息反应在屏幕上,来对系统进行操作,就是如今我们常用的编程方式。

    但随着计算机的普及,越来越多国家的文字和符号需要通过本地化来在互联网上为人们交流提供便利,于是就出了许多不同实现用于本地化的编码标准,后来为了统一Unicode也就应运而生。

  • Unicode码
    Unicode是国际组织制定的可以容纳世界上所有文字和符号的字符编码方案,也就是说世界上每种文字或符号都有一个对应的Unicode码。
    一般表示为U+一个四位的十六进制码,即两个字节,通常在程序调试时可以使用转义字符\u+[Unicode码]的字符串打印出对应的字符
    需要注意的是,Unicode 只是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储,于是出现了许多Unicode编码的实现方式。
    目前所说的Unicode编码普遍采用的是其中一种方式叫UCS-2,它用两个字节来编码一个字符。

  • UTF-8
    尽管Unicode解决了字节与字符之间的对应关系问题,但由于各种ASCII扩充字符集和其它标准的编码早已深入应用到各个领域,加上Unicode的编码方式仍然在某些情况相比ASCII来说占用存储资源要多,因此在选择编码方式上仍然没有得到统一。

    但随着互联网的发展,UTF-8使用越来越广,它便是Unicode的实现方式之一。
    UTF-8 最大的一个特点,就是它是一种动态变长的编码方式。它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度。
    UTF-8 的编码规则只有2条:

    1. 对于单字节的符号,字节的第一位设为0,后面7位为这个符号的 Unicode 码。因此对于英语字母,UTF-8 编码和 ASCII 码是相同的。
    2. 对于n字节的符号(n > 1),第一个字节的前n位都设为1,第n + 1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的 Unicode 码。
  • 使用Unicode码得到UTF—8的编码

    Unicode符号范围(16进制)UTF-8编码方式(二进制)
    0000 0000 ~ 0000 007F0xxxxxxx
    0000 0080 ~ 0000 07FF110xxxxx 10xxxxxx
    0000 0800 ~ 0000 FFFF1110xxxx 10xxxxxx 10xxxxxx
    0001 0000 ~ 0010 FFFF11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

    例如中的Unicode字符为4E2D在第三行的范围,二进制是100111000101101,也就是需要三个字节。利用上述规则得到UTF-8的二进制是11100100 10111000 10101101,转换成十六进制是E4 B8 AD

  • Unicode签名BOM
    windows的记事本在存储字符时会添加几个字节的十六进制码用来说明编码的类型,例如三个字节的EF BB BF表示是UTF-8编码,其它编码方式又对应不同的字节码,这也就是所谓的Unicode签名BOM(Byte Order Mark)。
    但是UTF-8的字节顺序是不变的,因此这个文件头实际上不起作用,有一些编程语言是ISO-8859-1编码,所以如果用UTF-8针对这些语言编程序,就必须去掉BOM,即保存成“UTF-8—无BOM”的格式才可以。

  • big endian和little endian
    big endian和little endian是CPU处理多字节数的不同方式。例如“汉”字的Unicode编码是6C49。那么写到文件里时,究竟是将6C写在前面,还是将49写在前面?如果将6C写在前面,就是big endian。如果将49写在前面,就是little endian。

  • 文本与二进制
    二进制:内容可以以十六进制码显示,更接近数据的本质形式。
    文本:内容以字符为主,更便于人类阅读。

    二进制文件与文本文件:二进制文件和文本文件在物理上没有区别,只是逻辑层次的不同。文本文件的本质也是二进制,但它使用了更容易被人类理解的字符形式。
    以上是比较广义的理解,比较狭义的理解是TXT表示文本文件(即文件中只包含ASCII码),而非文本文件则是二进制文件。

    二进制协议:抽象来说包括包头和包体,遵循网络通信协议标准,一般使用几个字节来包含包体长度及说明信息,使用包头中标注的长度的字节来存储命令及业务数据信息。
    文本协议:使用字符来说明数据包的起始、结尾和分隔信息及业务数据说明信息等,可读性更强。

  • 查看二进制文件
    可以使用一些HEX查看工具查看文件的十六进制字节码,例如在vscode中安装hexdump然后右击文件Show Hexdump最终会得到中间区域的字节码和查看器提供的额外信息。

  • 编码页codepage
    是一个经过挑选的以特定顺序排列的字符内码列表(内码表),CodePage的作用,是决定页面以何种编码方式显示动态内容。
    关于页码对应的编码可以参考MSDN这篇

  • 编码转换
    或者说内码转换,将某种编码方式得到的内码转换为另一种编码方式的内码。通常可以使用代码实现,如C#中的Encoding类。

  • C#中的编码与解码
    需要用到System.Text下的Encoding类
    C#中的字符类型是char类型,char是16位的Unicode字符,占两个字节.
    Encoding是个编码器基类,预置了几种静态类型的常用的编码器,另外还有一种静态方法 GetEncoding可以获取到一个编码器实例,还派生了几种编码器类。
    可以通过GetPreamble来获取到编码器中的签名BOM。

参考资料:
1. 阮一峰–《字符编码笔记》
2. 《编码的奥秘-隐匿在计算机背后的软硬件语言》—Charles Petzold 著 伍卫国 王宣政 孙燕妮等 译

©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页