使用字符串作为字节
Use string as bytes
我的问题如下:
我正在读取由某些软件生成的 .csv 并使用 Pandas 来读取它。 Pandas 正确读取 .csv,但其中一列存储表示向量的字节序列,Pandas 将它们存储为字符串。
所以我有 data(字符串),我想使用 np.frombuffer() 来获得正确的向量。问题是,data 是一个字符串,所以它已经编码,所以当我使用 .encode() 将它转换为字节时,序列不是原始序列。
示例:.csv 包含 \x00\x00,表示 dtype=np.uint8 的向量 [0,0]。 Pandas 将其存储为字符串,当我尝试处理它时,会发生如下情况:
data = df.data[x] # With x any row.
type(data)
print(data)
\x00\x00
e_data = data.encode("latin1")
print(e_data)
b'\\x00\\x00'
v = np.frombuffer(e_data, np.uint8)
print(v)
数组([ 92 120 48 48 92 120 48 48], dtype=uint8)
我只是想从数据中获取 b'\x00\x00' 而不是 b'\\x00\\x00' 我知道这是一个我还无法修复的编码混乱。
有什么办法吗?
谢谢!
问题:您(显然)有一个包含文字反斜杠转义序列的字符串,例如:
>>> x = r'\x00' # note the use of a raw string literal
>>> x # Python's representation of the string escapes the backslash
'\x00'
>>> print(x) # but it looks right when printing
\x00
据此,您希望创建一个相应的 bytes
对象,其中反斜杠转义序列被转换为相应的字节。
处理这些类型的转义序列是使用 unicode-escape
字符串编码完成的。您可能知道,字符串编码在 bytes
和 str
对象之间转换,指定字节序列对应于 Unicode 代码点的规则。
但是,unicode-escape
编解码器假定转义序列在等式的 bytes
一侧,而 str
一侧将具有相应的 Unicode 字符:
>>> rb'\x00'.decode('unicode-escape') # create a string with a NUL char
'\x00'
将 .encode
应用于字符串将反转该过程;所以如果你从反斜杠转义序列开始,它会重新转义反斜杠:
>>> r'\x00'.encode('unicode-escape') # the result contains two backslashes, represented as four
b'\\x00'
>>> list(r'\x00'.encode('unicode-escape')) # let's look at the numeric values of the bytes
[92, 92, 120, 48, 48]
如您所见,这显然不是我们想要的。
我们想从 bytes
转换为 str
以进行反斜杠转义。但是我们有一个 str
开始,所以我们需要将其更改为 bytes
;我们想要 bytes
最后,所以我们需要更改从反斜杠转义中获得的 str
。在这两种情况下,我们都需要使每个 Unicode 代码点从 0-255 包含在内,对应于具有相同值的单个字节。
我们那个任务所需的编码称为latin-1
,也称为iso-8859-1
。
例如:
>>> r'\x00'.encode('latin-1')
b'\x00'
因此,我们可以推断出整体转换:
>>> r'\x00'.encode('latin-1').decode('unicode-escape').encode('latin-1')
b'\x00'
根据需要:我们的 str
带有文字反斜杠、小写 x 和两个零,被转换为包含单个零字节的 bytes
对象。
或者:我们可以请求在解码时处理反斜杠转义,方法是使用codecs
标准库模块中的escape_decode
。然而,这个 isn't documented 并不是真的打算那样使用 - 它是用于实现 unicode-escape
编解码器和可能的其他一些东西的内部东西。
如果你想让自己暴露在未来崩溃的风险中,它看起来像:
>>> import codecs
>>> codecs.escape_decode(r'\x00\x00')
(b'\x00\x00', 8)
我们得到一个 2 元组,其中包含所需的 bytes
,我假设是已解码的 Unicode 代码点的数量(即字符串的长度)。根据我的测试,它似乎只能对非反斜杠序列使用 UTF-8 编码(但这可能特定于 Python 的配置方式),并且您无法更改它;对于 decode
方法,没有实际参数来指定编码。就像我说的 - 不适合一般用途。
是的,所有这些看起来都很尴尬。您无法轻松获得对此类事情的支持的原因是,这并不是您真正打算设计系统的方式。从根本上说,所有数据都是字节;文本是由该字节数据编码的抽象。使用单个字节(值为 0)表示文本的四个字符(符号 \
、x
、0
和 0
)不是正常编码,也不是一个可逆的(我怎么知道是将字节解码为这四个字符,还是解码为单个 NUL 字符?)。相反,您应该强烈考虑使用其他一些友好的数据字符串表示形式(可能是普通的十六进制转储)和一种与文本编码无关的方式来解析它。例如:
>>> data = '41 42' # a string in a simple hex dump format
>>> bytes.fromhex(data) # support is built-in, and works simply
b'AB'
>>> list(bytes.fromhex(data))
[65, 66]
我的问题如下:
我正在读取由某些软件生成的 .csv 并使用 Pandas 来读取它。 Pandas 正确读取 .csv,但其中一列存储表示向量的字节序列,Pandas 将它们存储为字符串。
所以我有 data(字符串),我想使用 np.frombuffer() 来获得正确的向量。问题是,data 是一个字符串,所以它已经编码,所以当我使用 .encode() 将它转换为字节时,序列不是原始序列。
示例:.csv 包含 \x00\x00,表示 dtype=np.uint8 的向量 [0,0]。 Pandas 将其存储为字符串,当我尝试处理它时,会发生如下情况:
data = df.data[x] # With x any row.
type(data)
print(data)
\x00\x00
e_data = data.encode("latin1")
print(e_data)
b'\\x00\\x00'
v = np.frombuffer(e_data, np.uint8)
print(v)
数组([ 92 120 48 48 92 120 48 48], dtype=uint8)
我只是想从数据中获取 b'\x00\x00' 而不是 b'\\x00\\x00' 我知道这是一个我还无法修复的编码混乱。
有什么办法吗?
谢谢!
问题:您(显然)有一个包含文字反斜杠转义序列的字符串,例如:
>>> x = r'\x00' # note the use of a raw string literal
>>> x # Python's representation of the string escapes the backslash
'\x00'
>>> print(x) # but it looks right when printing
\x00
据此,您希望创建一个相应的 bytes
对象,其中反斜杠转义序列被转换为相应的字节。
处理这些类型的转义序列是使用 unicode-escape
字符串编码完成的。您可能知道,字符串编码在 bytes
和 str
对象之间转换,指定字节序列对应于 Unicode 代码点的规则。
但是,unicode-escape
编解码器假定转义序列在等式的 bytes
一侧,而 str
一侧将具有相应的 Unicode 字符:
>>> rb'\x00'.decode('unicode-escape') # create a string with a NUL char
'\x00'
将 .encode
应用于字符串将反转该过程;所以如果你从反斜杠转义序列开始,它会重新转义反斜杠:
>>> r'\x00'.encode('unicode-escape') # the result contains two backslashes, represented as four
b'\\x00'
>>> list(r'\x00'.encode('unicode-escape')) # let's look at the numeric values of the bytes
[92, 92, 120, 48, 48]
如您所见,这显然不是我们想要的。
我们想从 bytes
转换为 str
以进行反斜杠转义。但是我们有一个 str
开始,所以我们需要将其更改为 bytes
;我们想要 bytes
最后,所以我们需要更改从反斜杠转义中获得的 str
。在这两种情况下,我们都需要使每个 Unicode 代码点从 0-255 包含在内,对应于具有相同值的单个字节。
我们那个任务所需的编码称为latin-1
,也称为iso-8859-1
。
例如:
>>> r'\x00'.encode('latin-1')
b'\x00'
因此,我们可以推断出整体转换:
>>> r'\x00'.encode('latin-1').decode('unicode-escape').encode('latin-1')
b'\x00'
根据需要:我们的 str
带有文字反斜杠、小写 x 和两个零,被转换为包含单个零字节的 bytes
对象。
或者:我们可以请求在解码时处理反斜杠转义,方法是使用codecs
标准库模块中的escape_decode
。然而,这个 isn't documented 并不是真的打算那样使用 - 它是用于实现 unicode-escape
编解码器和可能的其他一些东西的内部东西。
如果你想让自己暴露在未来崩溃的风险中,它看起来像:
>>> import codecs
>>> codecs.escape_decode(r'\x00\x00')
(b'\x00\x00', 8)
我们得到一个 2 元组,其中包含所需的 bytes
,我假设是已解码的 Unicode 代码点的数量(即字符串的长度)。根据我的测试,它似乎只能对非反斜杠序列使用 UTF-8 编码(但这可能特定于 Python 的配置方式),并且您无法更改它;对于 decode
方法,没有实际参数来指定编码。就像我说的 - 不适合一般用途。
是的,所有这些看起来都很尴尬。您无法轻松获得对此类事情的支持的原因是,这并不是您真正打算设计系统的方式。从根本上说,所有数据都是字节;文本是由该字节数据编码的抽象。使用单个字节(值为 0)表示文本的四个字符(符号 \
、x
、0
和 0
)不是正常编码,也不是一个可逆的(我怎么知道是将字节解码为这四个字符,还是解码为单个 NUL 字符?)。相反,您应该强烈考虑使用其他一些友好的数据字符串表示形式(可能是普通的十六进制转储)和一种与文本编码无关的方式来解析它。例如:
>>> data = '41 42' # a string in a simple hex dump format
>>> bytes.fromhex(data) # support is built-in, and works simply
b'AB'
>>> list(bytes.fromhex(data))
[65, 66]