zoukankan      html  css  js  c++  java
  • 关于编码问题的整理

    一、编码历史:

    1、ASCII(主要用于显示现代英语和其他西欧语言,其最多只能用 8 位来表示(一个字节),即:2**8 = 256-1,所以,ASCII码最多只能表示 255 个符号。

    2、为了处理汉字,程序员设计了用于简体中文的GB2312,但GB2312 支持的汉字太少,之后扩展规范为GBK,之后为GB18030(手机、MP3一般只支持GB2312)。从ASCII、GB2312、GBK 到GB18030,这些编码方法是向下兼容的。GB2312、GBK、GB18030都属于双字节字符

    3、因为ASCII码无法将世界上的各种文字和符号全部表示,所以,需要一种可以代表所有字符和符号的编码,即:Unicode(统一码、万国码、单一码),它为每种语言中的每个字符设定了统一并且唯一的二进制编码,规定字符和符号最少由16位来表示(2个字节),即:2 **16 = 65536。

    4、UTF-8,是对Unicode编码的压缩和优化,它是可变长度编码,很好的节省了空间。winx的操作系统安装时是默认的gbk编码,而linux操作系统默认的是utf8编码。

    二、py3的编码:

    Py3有两种数据类型:str和bytes,str类型存unicode数据,bytse类型存bytes数据。Python 3对文本和二进制数据作了更为清晰的区分,不再会对bytes字节串进行自动解码。文本总是Unicode,由str类型表示,二进制数据则由bytes类型表示。Python 3不会以任意隐式的方式混用str和bytes,这使两者的区分特别清晰。你不能拼接字符串和字节包,也无法在字节包里搜索字符串(反之亦然),也不能将字符串传入参数为字节包的函数(反之亦然)。

    在py3中encode,在转码的同时还会把string 变成bytes类型,decode在解码的同时还会把bytes变回string

    import json

    s = '苑昊'
    print(type(s) )#<class 'str'>
    print(json .dumps(s) )#"u82d1u660a"

    b=s.encode('utf-8')
    print(type(b))#<class 'bytes'>
    print(b)#b'xe8x8bx91xe6x98x8a'

    u=b.decode('utf-8')
    print(type(u) )#<class 'str'>
    print(u)#苑昊
    print(json .dumps(u) )#"u82d1u660a"

    print(len('苑昊'))#2

     

    三、文件从磁盘到内存的编码:

    文本编辑器比如word,我们在word上编辑的文字在保存之前数据是通过什么形式存在内存的呢?是unicode数据,这是因为它是万国码,任何字符它都有唯一编码对应,所以兼容性是最好的。

    当我们保存了的存到磁盘上的数据是通过某种编码方式编码的bytes字节串。比如utf8——一种可变长编码,很好的节省了空间,还有gbk编码等等。于是,在我们的文本编辑器软件都有默认的保存文件的编码方式,比如utf8,比如gbk。当我们点击保存的时候,这些编辑软件已经"默默地"帮我们做了编码工作。那当我们再打开这个文件时,软件又默默地给我们做了解码的工作,将数据再解码成unicode,然后就可以呈现明文给用户了!所以,unicode是离用户更近的数据,bytes是离计算机更近的数据。

    再说程序执行:先明确一个概念:py解释器本身就是一个软件,一个类似于文本编辑器一样的软件!现在让我们一起还原一个py文件从创建到执行的编码过程:

    打开pycharm,创建hello.py文件,写入

    s='苑昊'

    print(s)

       当我们保存的的时候,hello.py文件就以pycharm默认的编码方式保存到了磁盘;关闭文件后再打开,pycharm就再以默认的编码方式对该文件打开后读到的内容进行解码,转成unicode到内存我们就看到了明文;而如果我们点击运行按钮或者在命令行运行该文件时,py解释器这个软件就会被调用,打开文件,然后解码存在磁盘上的bytes数据成unicode数据,这个过程和编辑器是一样的,不同的是解释器会再将这些unicode数据翻译成C代码再转成二进制的数据流,最后通过控制操作系统调用cpu来执行这些二进制数据,整个过程才算结束。

    那么问题来了,我们的文本编辑器有自己默认的编码解码方式,我们的解释器有吗?

    当然有,py2默认ASCII码,py3默认的utf8,可以通过如下方式查询

    1

    2

    import sys

    print(sys.getdefaultencoding())

    常见的编码问题:

    cmd下的乱码问题

    hello.py

    #coding:utf8

    print ('苑昊')

    文件保存时的编码也为utf8。

    思考:为什么在IDE下用2或3执行都没问题,在cmd.exe下3正确,2乱码呢?

       我们在winx下的终端即cmd.exe去执行,大家注意,cmd.exe本身也一个软件;当我们python2 hello.py时,python2解释器(默认ASCII编码)去按声明的utf8编码文件,而文件又是utf8保存的,所以没问题;问题出在当我们print'苑昊'时,解释器这边正常执行,也不会报错,只是print的内容会传递给cmd.exe用来显示,而在py2里这个内容就是utf8编码的字节数据,可这个软件默认的编码解码方式是GBK,所以cmd.exe用GBK的解码方式去解码utf8自然会乱码。

    py3正确的原因是传递给cmd的是unicode数据,cmd.exe可以识别内容,所以显示没问题。

    明白原理了,修改就有很多方式,比如:

    print (u'苑昊')

    改成这样后,cmd下用2也不会有问题了。

    小蟒蛇
  • 相关阅读:
    解决跨操作系统平台JSON中文乱码问题
    httpencode编码
    DELPHI搭建centos开发环境
    cross socket和msgpack的数据序列和还原
    libmidas.so.2
    开发WINDOWS服务程序
    idhttp访问DATASNAP有密码验证的中间件
    接口操作XML
    HttpApplication中的异步线程
    Assembly类
  • 原文地址:https://www.cnblogs.com/pyxiaomangshe/p/7715880.html
Copyright © 2011-2022 走看看