zoukankan      html  css  js  c++  java
  • 字符串和编码

    一、为什么会有字符串编码问题?

      最开始的计算机只针对数字和英文字母进行编码,也就是ASCII码,但是随着计算机的普及,各种语言都需要编码,因此出现了一系列的标准,比如中国制定了GB2312,日本把日文编到Shift_JIS里,韩国把韩文编到Euc-kr里。所以各种编码混在一起就会出现乱码。

      Unicode编码应运而生。Unicode把所有语言都统一到一套编码里,这样就不会再有乱码问题了。

      Unicode标准也在不断发展,但最常用的是用两个字节表示一个字符(如果要用到非常偏僻的字符,就需要4个字节)。现代操作系统和大多数编程语言都直接支持Unicode。 

      也就是说一个汉字我们用两个字节16bytes来表示,一个英文字母也是如此,比如A就是00000000 01000001。这样一来,会出现很大的空间浪费,因此UTF-8出现了。

      UTF-8采取变长编码的方式,也就是说针对不同的字符采取不同的编码方式,例如英文字母用一个字节进行编码,一个汉字用三个字节来进行编码。

      如下可以看出几种编码的区别:

    字符ASCIIUnicodeUTF-8
    A 01000001 00000000 01000001 01000001
    x 01001110 00101101 11100100 10111000 10101101

    二、计算机中字符串的编码方式

    在计算机内存中,统一使用Unicode编码,当需要保存到硬盘或者需要传输的时候,就转换为UTF-8编码。

    也就是说在内存使用时,都用Unicode进行编码,当存储或者传输时,使用UTF-8编码来减少存储空间。

    用记事本编辑的时候,从文件读取的UTF-8字符被转换为Unicode字符到内存里,编辑完成后,保存的时候再把Unicode转换为UTF-8保存到文件:

    浏览网页的时候,服务器会把动态生成的Unicode内容转换为UTF-8再传输到浏览器:

     

    三、Python中的字符串

    python3中,字符串是以Unicode编码的,支持多种语言。

    对于单个字符的编码,Python提供了ord()函数获取字符的整数表示,chr()函数把编码转换为对应的字符:

    >>> ord('A')
    65
    >>> ord('中')
    20013
    >>> chr(66)
    'B'
    >>> chr(25991)
    '文'

    由于Python的字符串类型是str,在内存中以Unicode表示,一个字符对应若干个字节。如果要在网络上传输,或者保存到磁盘上,就需要把str变为以字节为单位的bytes

    Python对bytes类型的数据用带b前缀的单引号或双引号表示:

    x = b'ABC'

    'ABC'与b'ABC'之间是有区别的,两者表示的内容相同,但是占用的字节不同,前者占用6个字节,后者占用3个。

    以Unicode表示的str通过encode()方法可以编码为指定的bytes,例如:

    >>> 'ABC'.encode('ascii')
    b'ABC'
    >>> '中文'.encode('utf-8')
    b'xe4xb8xadxe6x96x87'
    >>> '中文'.encode('ascii')
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)

    可以看到,有些无法转化的格式会提示报错

    反过来,如果我们从网络或磁盘上读取了字节流,那么读到的数据就是bytes。要把bytes变为str,就需要用decode()方法:

    >>> b'ABC'.decode('ascii')
    'ABC'
    >>> b'xe4xb8xadxe6x96x87'.decode('utf-8')
    '中文'

    如果bytes中包含无法解码的字节,decode()方法会报错:

    >>> b'xe4xb8xadxff'.decode('utf-8')
    Traceback (most recent call last):
      ...
    UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 3: invalid start byte

    如果bytes中只有一小部分无效的字节,可以传入errors='ignore'忽略错误的字节:

    >>> b'xe4xb8xadxff'.decode('utf-8', errors='ignore')
    ''

    由于Python源代码也是一个文本文件,所以,当你的源代码中包含中文的时候,在保存源代码时,就需要务必指定保存为UTF-8编码。当Python解释器读取源代码时,为了让它按UTF-8编码读取,我们通常在文件开头写上这行:

    # -*- coding: utf-8 -*-

    申明了UTF-8编码并不意味着你的.py文件就是UTF-8编码的,必须并且要确保文本编辑器正在使用UTF-8 without BOM编码:

     

  • 相关阅读:
    IssueQuery failed in redmine rake tasks
    rubymine 调试 redmine
    redmine rake tasks
    rails tutorial sample app
    win7 chm 打开失败记录
    rails再体验(第一个程序)
    Bitnami Redmine插件开发记录
    redmine export long csv file failed: 502 proxy error
    Java时区切换时的需要注意
    Android No static field XXX of type I in class Lcom/XXX/R$id错
  • 原文地址:https://www.cnblogs.com/flightless/p/9886057.html
Copyright © 2011-2022 走看看