http字符集学习笔记

写在前面

  emoji表情对于用户来说是非常常见的输入,尤其是在移动端,对于emoji表情的处理如果不注意的话就很容易出错,对于我现在的这个项目来说就是可能因为一开始设计数据库的时候没有考虑到这个问题,现在数据多了现在改数据库不好改,只能在php代码中过滤掉emoji表情。对于我来说,仅仅在网上搜到解决方案自然远远是不够的,对于其中的一些原理,我也还要弄清楚。

字符集与http

  字符集指的是一种从二进制编码到某类字符符号的映射,而校对是指一组用于某个字符集的排序规则。
  http协议中与字符集相关的首部有Content-Type和charset参数,Content-Language,这两个首部是服务器端告诉客户端实体主题所使用的的字符集类型,而客户端使用Accept-Charset和Accept-Language首部告知服务器 它理解哪些字符集编码算法和语言以及其中的优先顺序。
  在html文档中也可以用对应的meta标签或者直接指定charset参数。

http中字符集如何工作

  
  我们想把文档中的二进制码转换为字符以便显示在屏幕上,我们需 要一种标准方法来描述并应用把二进制码转换为字符的解码算法。
  把二进制转换成字符主要经过几个步骤:
  1. 二进制代码转换成字符代码(a步骤)
  2. 从字符集中找到对应这个字符代码的字符元素(b步骤)
  3. 然后在显示器上使用字体和版式软件找到对应的显示字形

字符集术语

  1. 字符。字符是指字母、数字、标点、表意文字(比如汉语)、符号,或其他文本形式的 书写“原子”。由统一字符集(Universal Character Set,UCS, 它的非正式的名字 是 Unicode3)首创,为多种语言中的很多字符开发了一系列标准化的文本名称, 它们常用来便捷地命名字符,而且不会与其他字符冲突。
  2. 字形。描述字符的笔画图案或唯一的图形化形状。如果一个字符有多种不同的写法,就有多个字形。
  3. 编码后的字符。分配给字符的唯一数字编号,用于区分不同的字符,这样我们就可以操作它了。
  4. 代码空间。计划用于字符代码值的整数范围。
  5. 代码宽度。每个(固定大小的)字符代码所用的位数。
  6. 字符库。特定的工作字符集(全体字符的一个子集)。
  7. 编码后的字符集。组成字符库(从全球的字符中选出若干字符)的已编码字符集,并为每个字符 分配代码空间中的一个代码。换句话说,它把数字化的字符代码映射为实际的 字符。
  8. 字符编码方案。把数字化的字符代码编码成一系列二进制码(并能相应地反向解码)的算法。字符编码方案可用来减少识别字符所需要的数据总量(压缩)、解决传输限制、统一重叠编码字符集。字符编码主要有三种类型:
    1)固定宽度。固定宽度方式的编码用固定数量的比特表示每个编码后的字符。它们能被快速处 理,但可能会浪费空间。
    2)可变宽度(无模态)。可变宽度方式的编码对不同的字符代码数字采用不同数量的比特。对于常用字 符,这样可以减少需要的位数,而且还能在允许使用多字节来表示国际性字符的 同时,保持对传统 8 位字符集的兼容性。
    3)可变宽度(有模态)。有模态的编码使用特殊的“转义”模式在不同的模态之间切换。例如,可以用有 模态的编码在文本中使用多个互相有重叠的字符集。有模态的编码处理起来比较 复杂,但它们可以有效地支持复杂的书写系统。

常见编码方案

  1. 8位
  8 位固定宽度恒等编码把每个字符代码编码为相应的 8 位二进制值。它只能支持有 256 个字符代码范围的字符集。iso-8859 字符集家族系列使用的就是 8 位恒等编码。
  2. UTF-8 UTF-8 是一种流行的为 UCS 设计的字符编码方案,UTF 表示 UCS 变换格式(UCS Transformation Format)。UTF-8 为字符代码值使用的是无模态的变宽编码,第一字 节的高位表示编码后的字符所用的字节数,所需的每个后续字节都含有 6 位的代码 值。参见下表
  如果编码后的第 1 字节的最高位是 0,长度就是 1 字节,剩余的 7 位就包含字符的 代码。这样带来的美妙结果就是和 ASCII 兼容(但和 iso-8859 系列不兼容,因为 iso-8859 系列使用了最高位)。

字符代码的二进制位 字节1 字节2 字节3 字节4 字节5 字节6
0-7 0ccccccc - - - - -
8-11 110ccccc 10cccccc - - - -
12-16 1110cccc 10cccccc 10cccccc - - -
17-21 11110ccc 10cccccc 10cccccc 10cccccc - -
22-26 111110cc 10cccccc 10cccccc 10cccccc 10cccccc -
27-31 1111110c 10cccccc 10cccccc 10cccccc 10cccccc 10cccccc
例如,字符代码 90(ASCII 的“Z”)会被编码为 1 个字节(01011010),而代码 5073(13 位二进制值为 1001111010001)会被编码为 3 个字节:
11100001 10001111 10010001
还有例如ASCII字符集、GB2312字符集、BIG5字符集、GB18030字符集、Unicode字符集等,在这篇字符集和字符编码(Charset & Encoding)文章中有非常详细的讲解。

参考资料

  《http权威协议》
  字符编码(维基百科)
  字符集和字符编码(Charset & Encoding)
  字符编码笔记:ASCII,Unicode和UTF-8