字符串和字节字符串有什么区别?
- 2024-12-19 09:23:00
- admin 原创
- 83
问题描述:
我正在使用一个返回“字节字符串”的库(bytes
),我需要将其转换为字符串。
这两者之间真的有区别吗?它们之间有什么关系?我该如何进行转换?
解决方案 1:
计算机唯一可以存储的东西是字节。
要在计算机中存储任何东西,必须先对其进行编码,即将其转换为字节。例如:
如果您想存储音乐,您必须首先使用MP3、WAV等对其进行编码。
如果要存储图片,必须首先使用PNG、JPEG等对其进行编码。
如果要存储文本,必须首先使用ASCII、UTF-8等对其进行编码。
MP3、WAV、PNG、JPEG、ASCII 和 UTF-8 是编码的示例。编码是一种以字节为单位表示音频、图像、文本等的格式。
在 Python 中,字节字符串就是字节序列。它不是人类可读的。在底层,所有内容都必须转换为字节字符串,然后才能存储在计算机中。
另一方面,字符串(通常简称为“字符串”)是字符序列。它是人类可读的。字符串不能直接存储在计算机中,必须先进行编码(转换为字节字符串)。有多种编码可以将字符串转换为字节字符串,例如 ASCII 和 UTF-8。
'I am a string'.encode('ASCII')
上述 Python 代码将使用编码 ASCII 对字符串“I am a string”b'I am a string'
进行编码。上述代码的结果将是一个字节字符串。如果打印它,Python 会将其表示为。但请记住,字节字符串不是人类可读的,只是 Python 在打印它们时将它们从 ASCII 解码。在 Python 中,字节字符串由表示b
,后跟字节字符串的 ASCII 表示。
如果您知道用于对字节字符串进行编码的编码,则可以将其解码回字符串。
b'I am a string'.decode('ASCII')
上述代码将返回原始字符串'I am a string'
。
编码和解码是逆操作。所有内容在写入磁盘之前都必须进行编码,并且必须进行解码才能供人读取。
解决方案 2:
假设 Python 3(在 Python 2 中,这种差异定义得不太明确) - 字符串是字符序列,即unicode 代码点;这些是抽象概念,不能直接存储在磁盘上。字节字符串是一系列字节,这并不奇怪 -可以存储在磁盘上的东西。它们之间的映射是一种编码- 有很多这样的编码(并且可能有无限多的编码) - 您需要知道在特定情况下适用哪种编码才能进行转换,因为不同的编码可能会将相同的字节映射到不同的字符串:
>>> b'xcfx84oxcfx81xcexbdoxcfx82'.decode('utf-16')
'蓏콯캁澽苏'
>>> b'xcfx84oxcfx81xcexbdoxcfx82'.decode('utf-8')
'τoρνoς'
一旦知道要使用哪一个,就可以使用.decode()
字节字符串的方法从中获取正确的字符串,如上所述。为了完整起见,.encode()
字符串的方法与之相反:
>>> 'τoρνoς'.encode('utf-8')
b'xcfx84oxcfx81xcexbdoxcfx82'
解决方案 3:
注意:由于 Python 2 的生命周期结束已经非常接近,我将更详细地阐述我对 Python 3 的答案。
在 Python 3 中
bytes
由 8 位无符号值序列组成,而str
由表示人类语言文本字符的 Unicode 代码点序列组成。
>>> # bytes
>>> b = b'hx65llo'
>>> type(b)
<class 'bytes'>
>>> list(b)
[104, 101, 108, 108, 111]
>>> print(b)
b'hello'
>>>
>>> # str
>>> s = 'nai/u0308ve'
>>> type(s)
<class 'str'>
>>> list(s)
['n', 'a', 'i', '̈', 'v', 'e']
>>> print(s)
naïve
尽管bytes
和str
似乎以相同的方式工作,但它们的实例彼此不兼容,即bytes
和str
实例不能与>
和 等运算符一起使用+
。此外,请记住,比较bytes
和str
实例是否相等,即使用==
,即使它们包含完全相同的字符,也将始终评估为False
。
>>> # concatenation
>>> b'hi' + b'bye' # this is possible
b'hibye'
>>> 'hi' + 'bye' # this is also possible
'hibye'
>>> b'hi' + 'bye' # this will fail
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't concat str to bytes
>>> 'hi' + b'bye' # this will also fail
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only concatenate str (not "bytes") to str
>>>
>>> # comparison
>>> b'red' > b'blue' # this is possible
True
>>> 'red'> 'blue' # this is also possible
True
>>> b'red' > 'blue' # you can't compare bytes with str
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: '>' not supported between instances of 'bytes' and 'str'
>>> 'red' > b'blue' # you can't compare str with bytes
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: '>' not supported between instances of 'str' and 'bytes'
>>> b'blue' == 'red' # equality between str and bytes always evaluates to False
False
>>> b'blue' == 'blue' # equality between str and bytes always evaluates to False
False
处理使用内置函数返回的文件时,还存在bytes
另一个问题。一方面,如果您想要从文件读取或写入二进制数据,请始终使用二进制模式(如“rb”或“wb”)打开文件。另一方面,如果您想要从文件读取或写入 Unicode 数据,请注意计算机的默认编码,因此如有必要,请传递参数以避免意外。str
`open`encoding
在 Python 2 中
str
由 8 位值序列组成,而unicode
由 Unicode 字符序列组成。需要注意的是,如果仅由 7 位 ASCI 字符组成,str
则unicode
可以与运算符一起使用。str
str
使用辅助函数在 Python 2 中在和之间unicode
以及在 Python 3 中在bytes
和之间进行转换可能会很有用。str
解决方案 4:
让我们拿一个简单的单字符字符串'š'
并将其编码为一个字节序列:
>>> 'š'.encode('utf-8')
b'xc5xa1'
为了本例的目的,我们以二进制形式显示字节序列:
>>> bin(int(b'xc5xa1'.hex(), 16))
'0b1100010110100001'
现在,如果不知道信息是如何编码的,通常无法将其解码回来。只有当您知道使用了 UTF-8 文本编码时,您才能按照解码 UTF-8 的算法并获取原始字符串:
11000101 10100001
^^^^^ ^^^^^^
00101 100001
您可以将二进制数显示101100001
回字符串:
>>> chr(int('101100001', 2))
'š'
解决方案 5:
来自什么是 Unicode?:
从根本上讲,计算机只处理数字。它们通过为每个字母和其他字符分配一个数字来存储它们。
......
Unicode 为每个字符提供了一个唯一的编号,无论什么平台,无论什么程序,无论什么语言。
因此,当计算机表示字符串时,它会通过字符的唯一 Unicode 编号查找存储在计算机中的字符,这些数字存储在内存中。但是您不能通过其唯一的 Unicode 编号直接将字符串写入磁盘或在网络上传输字符串,因为这些数字只是简单的十进制数。您应该将字符串编码为字节字符串,例如UTF-8。UTF-8 是一种能够对所有可能字符进行编码的字符编码,它将字符存储为字节(看起来像这样)。因此编码的字符串可以在任何地方使用,因为几乎所有地方都支持 UTF-8。当您从其他系统打开以 UTF-8 编码的文本文件时,您的计算机将对其进行解码并通过其唯一的 Unicode 编号显示其中的字符。
当浏览器从网络接收到UTF-8编码的字符串数据时,它会将数据解码为字符串(假设浏览器采用UTF-8编码)并显示该字符串。
在 Python 3 中,你可以将字符串和字节字符串相互转换:
>>> print('中文'.encode('utf-8'))
b'xe4xb8xadxe6x96x87'
>>> print(b'xe4xb8xadxe6x96x87'.decode('utf-8'))
中文
总之,字符串是为了在计算机上显示给人看的,而字节字符串是为了存储到磁盘和数据传输的。
解决方案 6:
Unicode 是字符和各种格式(例如,小写/大写、换行符和回车符)以及其他“事物”(例如,表情符号)的二进制表示的约定格式。计算机存储 Unicode 表示(一系列位)的能力(无论是在内存中还是在文件中)不亚于存储 ASCII表示(不同的一系列位)或任何其他表示(一系列位)。
为了进行沟通,沟通双方必须就使用何种表示方式达成一致。
由于 Unicode 力图表示人与人之间和计算机之间通信中使用的所有可能的字符(以及其他“事物”),因此与其他力图表示一组更有限的字符/事物的表示系统相比,它需要更多的位数来表示许多字符(或事物)。为了“简化”,也许是为了适应历史用法,Unicode 表示几乎完全转换为其他表示系统(例如 ASCII),以便在文件中存储字符。
这并不是说 Unicode不能用于在文件中存储字符,或通过任何通信渠道传输字符。只是事实并非如此。
术语“字符串”没有精确的定义。“字符串”在其常见用法中是指一组字符/事物。在计算机中,这些字符可以以多种不同的逐位表示形式存储。“字节字符串”是使用八位(八位称为一个字节)表示存储的一组字符。由于如今计算机使用 Unicode 系统(由可变数量的字节表示的字符)将字符存储在内存中,并使用字节字符串(由单个字节表示的字符)将字符存储到文件中,因此在将内存中表示的字符移动到文件中之前必须进行转换。
解决方案 7:
字符串是一串串在一起的项目。字节字符串是字节序列,例如b'xcexb1xcexac'
表示"αά"
。字符串是一串字符,例如"αά"
。与序列同义。
字节串可以直接存储到磁盘,而字符串(字符串)不能直接存储在磁盘上,他们之间的映射就是编码。
解决方案 8:
简单来说,想想我们的自然语言,如英语、孟加拉语、中文等。说话时,所有这些语言都会发出声音。但即使我们听到了,我们能理解它们吗?
答案通常是否定的。所以,如果我说我懂英语,那就意味着我知道这些声音是如何编码成一些有意义的英语单词的,我只需以同样的方式解码这些声音就可以理解它们。所以,其他语言也是如此。如果你懂,你脑子里就有这种语言的编码器-解码器包,如果你不懂,你就没有这个。
数字系统也是如此。就像我们自己一样,我们只能用耳朵听声音,用嘴发出声音,计算机只能存储字节和读取字节。因此,某些应用程序知道如何读取字节并解释它们(例如要考虑多少字节才能理解任何信息),并以相同的方式写入,以便其他应用程序也能理解它。但如果没有理解(编码器-解码器),写入磁盘的所有数据都只是字节串。
解决方案 9:
Python 语言将str
和bytes
作为标准“内置类型”。换句话说,它们都是类。我认为没有必要试图解释 Python 为何以这种方式实现。
话虽如此,str
和bytes
彼此非常相似。两者共享大部分相同的方法。以下方法是该类独有的str
:
casefold
encode
format
format_map
isdecimal
isidentifier
isnumeric
isprintable
以下方法是bytes
该类所特有的:
decode
fromhex
hex
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理必备:盘点2024年13款好用的项目管理软件