zoukankan      html  css  js  c++  java
  • 编码和解码(2)

    在电脑上处理文字的时候,你可能经常接触到一个名词,叫UTF-8.

    你会不会觉得一丝疑惑,这到底是什么东西?
    用一句话说明的话,UTF-8是一种编码格式,一个字节包含8个比特。
    等会,什么是编码,什么又是比特?为什么要用这个东西?
    那我们从基础说起,简单的介绍一下基本概念:

    编码
    我们都知道人有人的语言,计算机有计算机的语言,就是机器语言,所谓的二进制,0和1,1代表有一个信号,0表示没有信号。
    那怎么把人的语言翻译成机器语言呢,就需要一个字典,字典就是ASCII,
    如下图,左边是这个行为就是编码,左边是机器可以识别的ASCII码,
    右面是代表的字符,比如 00100001 代表 "!", 从左到右转换就是解码 (decode),从右到左就是编码 (encode)。

    因为ASIIC码有8位数,每位是一个比特 (bit),8位就是一个字节 (byte)。除了第一位是0,
    其他7位都可以有0 或者 1 两个选择,所以ASCII 一共可以表示 2^7 ,也就是128个字符。包括a-z 大小写,0-9 数字 和一些标点符号等。
    其中真正可读的只有95 个字符,其他的都是一些控制符,比如NUL,代表NULL。

    对于英语来说, ASCII 包括所有的字母了,但是对于其他的语言来说,比如汉语,当然95个字符远远不够。
    有人说ASCII的第一位只能是0很浪费,如果也可以是1 的话, 就会多128个组合,一共256个。然而这样也不够。所以我们有:

    多字节编码
    上述编码是单字节编码, 也就是只有8个比特。
    如果想匹配多于256个字符的语言,一个字节显然不够,用两个字节的话,16比特,可以编码65536个字符,BIG-5就是一个双字节编码方式,它包括大多数中文繁体字GB18030 则包括繁体和简体。比如

    这样每种语言可能都有他们的编码体系,用着不同的字节,对于人和机器来说,这样都很容易混乱。所以我们有:

    统一编码 Unicode
    像上文说的,对于一些语言单字节编码不够,所以采用双字节,双字节也不够的时候可以采用三字节,甚至四字节,字节是不是越多越好呢?
    并不是,因为字节用的越多,那些用单字节就能表示的字符会增加很多个0, 浪费很多容量。比如 A 可能就是00000000 00000000 00000000 01000001, 这样就没有必要了。

    如果一个人想写不同的语言,那他最好使用Unicode。 Unicode 用多少个字节呢?
    0个。

    因为Unicode其实不是一种编码, 而是定义了一个表, 表中为世界上每种语言中的每个字符设定了统一并且唯一的码位 (code point),以满足跨语言、跨平台进行文本转换的要求。在表示一个Unicode的字符时,通常会用“U+”然后紧接着一组十六进制的数字来表示这一个字符。如下图。

     比如一个人想写一篇文章,包括英语和日语,单字节编码可以表示英语,

    但是显然不能满足他写日语,因为他需要3个字节才能表示一个『あ』,也就是11100011 10000001 10000010。
    他可以用双字节编码,这样他只需要一个双字节,也就是00110000 01000010。
    所以他可以选择语言最高所需要的编码,也就是UTF-16.
    如果他只需要写英语, 那UTF-8就可以。

    UTF-8
    UTF-8的特点是对不同范围的字符使用不同长度的编码。

     上表表示如何从一个从Unicode 转化到UTF-8 , 对于前0x7F的字符,UTF-8编码和ASCII码是一一对应的。

    如果一个字符在000800-00FFFF 之间,那转化到UTF-8 需要用三字节模板,使用16个码位,每个x 就是一个码位。
    比如『汉』这个字的Unicode编码是0x6C49。0x6C49在0x0800-0xFFFF之间,使用3字节模板:1110xxxx 10xxxxxx 10xxxxxx。将0x6C49写成二进制是:0110 1100 0100 1001, 用这个比特流依次代替模板中的x,得到:11100110 10110001 10001001。
    当然如果用16位更节约空间。对于中文而言,Unicode 16编码里面已经包含了GB18030里面的所有汉字(27484个字)。

    Unicode的好处
    如果一个语言支持Unicode, 说明它本身一个字符就是单字节,比如英语:

    >>> string_e = 'hello'
    >>> string_e[0]
    'h'
    每个字符都是一个8位的字符串。所以在Python 里用字符串的截取功能[], 就会给我们第一个字节,同时也是一个字符 h。

    如果是汉语,在UTF-8 中三个字节才能代表一个字符。如果我们同样使用截取[]:

    >>> string = '汉字'
    >>> string[0]
    'xe6'
    只会给我们返回一个「汉」这个字的第一个字节, 也就是11100110, 但是「汉」需要用11100110 10111100 10100010 才能表示。那我们要怎么才能截取汉字的第一个字符呢?

    >>> string_u = string.decode('UTF-8')
    >>> string_u[0]
    u'u6c49'
    >>> print(string_u[0].encode('UTF-8'))

    将「汉字」解码到Unicode, 这时再截取第一个字符就是一个 u 开头的Unicode了,再用UTF-8 编码, 返回的就是「汉」 这个字符了。

    原文地址

    人各有命,上天注定,有人天生为王,有人落草为寇。脚下的路,如果不是你自己的选择,那么旅程的终点在哪,也没人知道。你会走到哪,会遇到谁,都不一定。
  • 相关阅读:
    有道翻译js解密(1)
    Python面试题之Python正则表达式re模块
    go语言从例子开始之Example4.常量
    go语言从例子开始之Example3.变量
    go语言从例子开始之Example2.类型
    go语言从例子开始之Example1.helloworld
    python模块打补丁
    gevent协程之猴子补丁带来的坑
    charles抓包小程序
    httptesting HTTP(s)接口自动化测试框架
  • 原文地址:https://www.cnblogs.com/ZkbFighting/p/14419458.html
Copyright © 2011-2022 走看看