我有一个csv文件,其中有两列,例如:
1621324695.083352,bytearray(b'x00x00x14Gx00x00nxfe')
第一个值是时间戳,另一个值是数据。
我的问题是,当我尝试用pd.read_csv()
读取文件时,bytearray
的值会变成字符串。有没有办法告诉python它已经是bytearray
值了?
当我使用函数bytearray()
时,它输出:bytearray(bytearray(b'...'))
。
在该文件中没有字节数组,只有它的文本表示(纯文本(。我们需要从中重新构建字节数组
要将像"bytearray(b'x00x00x14Gx00x00nxfe')"
这样的字符串转换为真正的字节数组,第一个想法通常是使用eval
,但有充分的理由尽可能避免使用eval
。
我们可以简单地从字符串中提取参数,处理其中的转义序列(如x00
和n
(,并将结果传递给bytearray()
,以创建最终对象。
要提取参数,请使用例如正则表达式。如果格式是固定的,简单的工具就可以了。
转义序列可以使用'unicode-escape'
解码器取消转义,但我们必须从字符串转换为字节。latin1
只是8位ASCII的名称,即字节数组使用的0-255值。
一个简单的演示:
inp = r"bytearray(b'x00x00x14Gx00x00nxfe')"
if inp.startswith("bytearray(b'") and inp.endswith("')"):
arg = inp[12:-2] # strip bytearray(b' and '), leave the string in between
unesc = arg.encode('latin1').decode('unicode-escape')
ba = bytearray(unesc, 'latin1')
print(f"result: {ba!r}")
else:
print("parse error!")
ba
是实字节数组,其表示repr(ba)
等于inp
如果您控制csv的创建,那么在将字节数组写入csv时,最好对其进行base64编码,然后在数据帧中解码。
这种方法通常比字符串化二进制对象要好,后者通常需要在其他应用程序使用二进制对象时进行破解。此外,如果使用-bb标志执行Python,字符串化字节将引发异常。Base64编码通常用于在文本环境中对二进制数据进行编码。
首先,让我们制作一些二进制数据
import base64
import csv
import io
import zlib
import pandas as pd
# Create some binary data
bas = [bytearray(zlib.compress(bytearray(w.encode('ascii')))) for w in ['hello', 'goodbye']]
print(bas)
输出:
[bytearray(b'xx9cxcbHxcdxc9xc9x07x00x06,x02x15'),
bytearray(b'xx9cKxcfxcfOIxaaLx05x00x0bxaax02xea')]
现在将其写入内存中的csv(或创建csv文件,为了方便起见,我们在这里使用缓冲区(,应用base64编码
buf = io.StringIO()
writer = csv.writer(buf)
writer.writerow(['id', 'binary_data'])
for i, ba in enumerate(bas):
# Base64-encode the binary data and decode from bytes to str
encoded = base64.b64encode(ba).decode('ascii')
writer.writerow([i, encoded])
buf.seek(0)
将csv读取到数据帧中
# Read the csv into a dataframe
df = pd.read_csv(buf)
print(df)
输出:
id binary_data
0 0 eJzLSM3JyQcABiwCFQ==
1 1 eJxLz89PSapMBQALqgLq
现在从base64解码以获得二进制数据
df['binary_data'] = df['binary_data'].apply(lambda cell: base64.b64decode(cell))
print(df)
输出
id binary_data
0 0 b'xx9cxcbHxcdxc9xc9x07x00x06,x02x15'
1 1 b'xx9cKxcfxcfOIxaaLx05x00x0bxaax02xea'
我们得到的是bytes
而不是bytearray
,但这通常并不重要——这两种类型基本上是可互换的。