人类使用文本,计算机使用字节序列
Python3字符编码
Python3的字符串类型是str,在内存中以Unicode表示,一个字符对应若干个字节。如果要在网络上传输,或者保存到磁盘上,就需要把str变为以字节为单位的bytes。在将字节转为字符的时候,如果编码方式不对,就会出现乱码。
Python对bytes类型的数据用带b前缀的单引号或双引号表示(b'123'),使用的编码为ASCII,所以不能存储中文
编码解码过程:
Unicode三明治--目前处理文本的最佳实践
bytes ---decode()--> str(Unicode) ---encode()---> bytes
Python3的字符串与字节
| 类型 | 编码 | 示例 | |
|---|---|---|---|
| 字符串 | str | Unicode | "123中" |
| 字节 | bytes | ASCII | b"123" |
Python3字符串中的u,b,r前缀
| 字符串前缀 | 编码方式 | 作用 | 示例 |
|---|---|---|---|
| u或无前缀 | Unicode | 表示字符串 | u"123"或"123" |
| b | ASCII | 表示字节 | b"123" |
| r | Unicode | 清除转义,所有字符都为普通字符 | r"F:/Python" |
ASCII、Unicode和UTF-8区别
编码方式是一种规则,与编程语言无关,在Python、Java和SQL中都是一样的。
| 编码 | 字节 | 字符 | 目的 | 使用场景 |
|---|---|---|---|---|
| ASCII | 1 | 英文字母、数字、符号 | ||
| Unicode | 2+ | 所有字符 | 统一标准,解决乱码 | 计算机内存 |
| UTF-8 | 1-6 | 所有字符 | 减少编码长度,方便传输、存储 | 存储、传输 |
Unicode 字符编码标准是固定长度的字符编码方案,它包含了世界上几乎所有现用语言的字符。在最初的版本中,两个字节的Unicode最多只能表示65535个字符,所以之后的版本对Unicode有扩充。
UTF-8又称为可变长编码,是Unicode 的实现方式。
为什么中文在UTF-8里需要占用3个字节,在Unicode中占用2个字节?
也就是说,UTF-8的目的是减少编码长度,那只会比Unicode短,为什么还会比它长呢?
这是由于UTF-8的编码规则决定的,由于utf-8规则天然占用字节前几位,若与Unicode同样用2字节16位表示一个中文字符,则utf-8除去规则占用,只剩余16-5=11位,无法表示Unicode下的两个字节(16位)所表示的字符。所以UTF-8使用了3个字节。
另外,UTF-8中英文字符占用一个字节;绝大多数汉字(基本汉字)占用三个字节,个别汉字占用四个字节。
UTF-8 编码规则
- 对于单字节的符号,字节的第一位设为0,后面7位为这个符号的 Unicode 码。因此对于英语字母,UTF-8 编码和 ASCII 码是相同的,即UTF-8编码能够兼容ASCII。
- 对于n字节的符号(n > 1),第一个字节的前n位都设为1,第n + 1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的 Unicode 码。
下表总结了编码规则,字母x表示可用编码的位。
| Unicode编码 | UTF-8编码 | 解释 |
|---|---|---|
| (十六进制) | (二进制) | Unicode部分为16进制编码, UTF-8编码为2进制 |
| 0000 0000-0000 007F | 0xxxxxxx | UTF-8规定,若1字符=1字节,首位须为‘0’ |
| 0000 0080-0000 07FF | 110xxxxx 10xxxxxx | UTF-8规定,若1字符=2字节,高位字节前3位为‘110’,低位前2位为‘10’ |
| 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx | UTF-8规定,若1字符=3字节,高位字节前3位为‘110’,后面低位前2位一律为‘10’(占4,5字节字符规则以此类推) |
Java中的字符编码
要分清内码(internal encoding)和外码(external encoding)。
- 内码 :某种语言运行时,其char和string在内存中的编码方式。
- 外码 :除了内码,皆是外码。源代码编译产生的目标代码文件(可执行文件或class文件)中的编码方式属于外码。
Java中的字符编码
- java中内码(运行内存)中的char使用UTF16的方式编码,一个char占用两个字节,但是某些字符需要两个char来表示。所以,一个字符会占用2个或4个字节。
- java中外码中char使用UTF8的方式编码,一个字符占用1~6个字节。
- UTF16编码中,英文字符占两个字节;绝大多数汉字(尤其是常用汉字)占用两个字节,个别汉字(在后期加入unicode编码的汉字,一般是极少用到的生僻字)占用四个字节。
String.getBytes()是一个用于将String的内码转换为指定的外码的方法。无参数版使用平台的默认编码作为外码,有参数版使用参数指定的编码作为外码;将String的内容用外码编码好,结果放在一个新byte[]返回。