zoukankan      html  css  js  c++  java
  • 撸一撸 编码的问题

    不知不觉中这篇文章成了我阅读量最高的文章。但是感觉自己写的不是很好。

    如果大家感觉对自己帮助不大,可以去看下阮一峰大大的这篇文章:http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html

    自始至终都没有捋一捋关于编码的问题,偶尔遇到问题就decode,encode解决了。
    今天来整理一下关于编码的问题。如有错误还请大家指出。

    编码

    • 系统编码
      我们都知道计算机存储信息都是以二进制的形式保存的,而且网络中信息的传输也都是以字节的形式进行传输的。那么我们看到汉字,中文都是怎么来的呢?说到这里大家可能想到了ASCII码表,ASCII码使用指定的7位或8位二进制数组合来表示128或256种可能的字符。如在ASCII表中 65对应的是字母A,那么某个值为65的字节或者字节串就代表了A。当然英文字母的表现使用一个字节就足够了,一个字节能表示的字符有256个。但是世界范围内的字符远远不止256个,于是就诞生了GB2312,GBK,unicode多种码表。其中unicode每个字符使用两个字节来表示,理论上能表示65536个字符,而且unicode包含各国大多数常用字符,被作为一种国际码表使用。这个码表就是系统所使用的码表。在存储信息或者读取信息的时候都是通过码表来进行的。不同的系统有着不同的默认码表,
    • Python编辑器编码
      首先我们在编辑代码的时候肯定使用的是所在操作系统的码表。而我们在python文件开头声明的#coding=utf-8 是指python在读取代码的时候使用utf-8的编码方式读取。
      下边会大概说一下utf-8与unicode的关系。python会有默认的编码(Python2是ascii,Python3是utf-8),这个默认编码是指对某个字符处理时使用的编码格式,但是对于文件读取,如果不指定编码格式的话,会使用操作系统默认的编码格式。

    UTF-8 和 unicode的关系

    Unicode只是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储。
    
    比如,汉字“严”的unicode是十六进制数4E25,转换成二进制数足足有15位(100111000100101),也就是说这个符号的表示至少需要2个字节。
    表示其他更大的符号,可能需要3个字节或者4个字节,甚至更多。
    
    这里就有两个严重的问题,第一个问题是,如何才能区别unicode和ascii?计算机怎么知道三个字节表示一个符号,
    而不是分别表示三个符号呢?第二个问题是,我们已经知道,英文字母只用一个字节表示就够了,如果unicode统一规定,
    每个符号用三个或四个字节表示,那么每个英文字母前都必然有二到三个字节是0,
    这对于存储来说是极大的浪费,文本文件的大小会因此大出二三倍,这是无法接受的。
    
    它们造成的结果是:
        对于单字节的符号,字节的第一位设为0,后面7位为这个符号的unicode码。因此对于英语字母,UTF-8编码和ASCII码是相同的。
        对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的unicode码。
    摘自https://www.cnblogs.com/csguo/p/7402121.html#4532275。
    
    

    综上所述 utf-8 是unicode用来表现字符二进制的一种形式。举个列子
    python2下:

    #coding=utf-8
    
    s = "小"
    
    print(s.decode(encoding='utf-8'), type(s.decode(encoding='utf-8')))
    print(s.decode(encoding='utf-8').encode(encoding='utf-8'), type(s.decode(encoding='utf-8').encode(encoding='utf-8')) )
    

    输出为:

    (u'u5c0f', <type 'unicode'>)
    ('xe5xb0x8f', <type 'str'>)
    

    输出的第一行的u'u5c0f'十六进制代表十进制数23567。是指unicode码表中"小"对应的数值为233567,转化为二进制的形式是 10111000 0001111。

    对照 Unicode符号范围 |UTF-8编码方式

    # 0000 0000-0000 007F | 0xxxxxxx
    #
    # 0000 0080-0000 07FF | 110xxxxx 10xxxxxx
    #
    # 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx10xxxxxx
    #
    # 0001 0000-0010 FFFF | 11110xxx 10xxxxxx10xxxxxx10xxxxxx
    

    5c0f 处于第三栏位,所以UTf-8表现5c0f 需要三个字节。格式转化的标准为:unicode的两个字节倒着填进'x'中,按照从后向前的方式。
    那么经过转化,10111000 0001111 ====> 11100101 10110000 10001111 ====> 229 176 143 ====> xe5xb0x8f
    与第二行打印的byte符合。

  • 相关阅读:
    Kotlin学习系列(三)
    获取Android设备标识符
    Kotlin学习系列(二)
    ijkplayer实现IMediaDataSource
    Fresco添加HTTP请求头
    Kotlin学习系列(一)
    完整的Android MVP开发之旅
    Marshmallow权限使用
    APP设计与开发(ui篇)
    下载Android源码
  • 原文地址:https://www.cnblogs.com/dg-blog/p/12581935.html
Copyright © 2011-2022 走看看