python中字符,字节,编码格式等问题总结

python中字符,字节,编码格式等问题总结

一直以来,对python中的字符,字节,编码格式理解的懵懵懂懂的,遇到问题总是搞不清楚,最近看一些网络传输方面的知识时,刚好要用到这些知识,总结一下以备以后复习。

byte

首先说byte,也叫字节,一个字节是8个bit。在python中,最小的数据存储单位就是字节,ASCII码中字符在python中都是占一个字节的存储位。

英文字符和字符串

英文字符都包含在ASCII编码中,所以所有的英文字符都是占1个字节的,(注意字符和单词的区别)

s= 'a'
print(s.encode('utf8'))
print(s.encode('gbk'))
print(len(s.encode('gbk')))
# 结果
b'a'
b'a'
1

这里看到我们采用分别utf8gbk两种编码方式将字符串s(python中字符串和字符不区分,这个和其他编程语言的string和char 是有区别的)进行编码,得出的字节码都是b'a' ,这个前缀b就表示这是一个byte类型的数据。长度是1,也就是占一个字节。如果将a改成apple结果是什么,你们可以自己试验。

汉字

因为计算机是美国人发明的,所以他们的英文字符集就很好处理,但是汉字的字符在计算机中应该怎么保存呢?这里就牵扯到了编码和解码,针对汉字的编码最常用的有utf8gbk,在网络传输或者字符存储的时候就需要把字符先编码成字节码,然后再发送/存储。在接收或读取的时候进行解码。

han = '中'
print(len(han))
print(han.encode('utf8'))
print(han.encode('gbk'))
print(len(han.encode('utf8')))
print(len(han.encode('gbk')))
# 结果
1
b'\xe4\xb8\xad'
b'\xd6\xd0'
3
2
  • 对照这个例子我们详细讲解一下,变量han是一个汉字字符串,第2行的输出结果是1,也就是说这个字符串的长度是1,这里汉字和英文字符的字符串长度都是一样的,简单点讲就是数单个字符的个数,就是字符串长度。

  • 第3行就汉字进行了utf8编码,第4行是gbk编码,将转成了字节码,但是从第9,10行的输出来看,它们完全不同,也就是说不同的编码方式对同一个字的编码结果是完全不同的。

  • 第5,6行分别打印两种编码方式下一个汉字所占的字节长度,从第11,12行就能看出,一个汉字如果采用utf8编码时,占3个字节,而采用gbk编码时只占了2个字节。所以说如果一大段数据如果都是中文字符的话,采用gbk编码将会大大节省存储空间或者网络带宽。但是还是不建议你这么做,因为考虑到兼容性,现在普遍的编码方式都是utf8

    最后,** 切记!!!**解码就是对编码的逆过程,所以采用了什么方式编码,就必须用同样的方式进行解码,否则肯定会报错。

数字(整型)

在网络传输中对数字也是编码成字节码进行传输的。int型字符直接调用int.to_bytes()方法进行编码

i = 65
print(i.to_bytes(4,byteorder='big',signed=False))
print(i.to_bytes(8,byteorder='big',signed=False))
# 结果
b'\x00\x00\x00A'
b'\x00\x00\x00\x00\x00\x00\x00A'
  • to_bytes()方法中需要传入3个参数
    • 第一个参数是字节长度,也就是说65这个数字你需要编码成占多少个字节长度的字符?
    • 第二个参数表示的字节序是什么,这里有biglittle两种选项(大端和小端),大端和小端不懂的可以自行度娘,这里不做展开
    • 第三个参数表示是无符号数还是有符号数,这里有符号和无符号也不做展开,具体请百度C语言的signedunsigned

这样就完成了对整型数据的编码,解码也是逆序,使用int.from_bytes()方法进行解码:

i = 65
i_byte_4 = i.to_bytes(4,byteorder='big',signed=False)
print(i_byte_4)
i_byte_8 = i.to_bytes(8,byteorder='big',signed=False)
print(i_byte_8)
i_decode_4 = int.from_bytes(i_byte_4,byteorder='big',signed=False)
print(i_decode_4)
i_decode_8 = int.from_bytes(i_byte_8,byteorder='big',signed=False)
print(i_decode_8)
# 结果
b'\x00\x00\x00A'
b'\x00\x00\x00\x00\x00\x00\x00A'
65
65

需要特别注意的是:解码时,from_bytes()中传入的后两个个参数要和to_bytes()严格对应,否则解码肯定出错

网络数据包的编解码

  • 数据包的收发流程
    - 发送端 当客户端给服务端发送数据包的时候一般先发送数据的长度,然后再发送数据包内容
    - 接收端 接收端接到第一包数据是数据包的长度,根据数据包的长度再接收数据包长度个字节的数据,然后根据协议定义就能解出数据包的内容

  • 数据包结构
    - 数据包一般的结构会包括,包头(数据长度4字节+数据包类型2字节+数据包加密类型1字节+保留字段1字节)+ 包内容(N字节)
    - 当接收端收到第一包数据,解出包长度以后,根据包长度接收包长度个字节的数据,然后根据上面的协议,逐段切片分割,就可以分别得到包头和包内容

这里注意的是,网络中发送的数据包都是字节码,所以在发送的时候,对不同的数据格式就要进行数据编码,而在接收的时候同样按照接收的数据的编码方式进行解码,这样就能得到原始数据。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值