按原样将字符串转换为字节对象

时间:2019-07-03 22:18:27

标签: python python-3.x

如何按原样将字符串转换为字节对象,即不对其进行编码。我不能在这里使用.encode(),因为它保存后破坏了我的二进制文件。

filedata = pathlib.Path('file.bin').read_bytes()
# since i can't modify a bytes object, i should convert it to a string, should I?
data = ''
for i in filedata:
    data += chr(i) if isinstance(i, int) else i
data[3] = '\x01'
data += '\x58\x02\x0C\x80\x61\x39\x56\x18\x55\x61\x89\x42\x42\x16\x46\x17\x54\x70\x10\x58\x60\x10\x10\x01\x75\x10\xF0\xC0\x00\x01\x00\x02\x00\xC0\x00\xD0\x00\x01\x00\xC4\x00\x01\x00\x02\x00\x01\x00\x00\x02\x00\x00\x00'
pathlib.Path('result.bin').write_bytes(data.encode()) # doesn't work as it should

所以代替这个:

58 02 0C 80 61 39 56 18 55 61 89 42 42 16 46 17 54 70 10 58 60 10 10 01 75 10 F0 C0 00 01 00 02 00 C0 00 D0 00 01 00 C4 00 01 00 02 00 01 00 00 02 00 00 00

我明白了:

58 02 0C C2 80 61 39 56 18 55 61 C2 89 42 42 16 46 17 54 70 10 58 60 10 10 01 75 10 C3 B0 C3 80 00 01 00 02 00 C3 80 00 C3 90 00 01 00 C3 84 00 01 00 02 00 01 00 00 02 00 00 00

我尝试修改字节对象本身,但是我总是收到该错误:

  

TypeError:“字节”对象不支持项目分配

我是Python的新手,所以我不知道是否有更好的方法来做到这一点。


已解决(感谢约翰):

filedata = bytearray(pathlib.Path(sys.argv[1]).read_bytes())
# filedata = bytearray(open(sys.argv[1], 'rb').read()) also works
filedata[1] = 255 # modifying a single byte (0 - 255)
filedata[0:1] = b'\xff' # inserting bytes
filedata.extend(255) # appending one single byte
filedata.extend(filedata2) # appending another array of bytes (bytearray object)
filedata.extend(b'\xff\xff') # appending bytes
filedata.extend([255, 255]) # appending bytes too
pathlib.Path(sys.argv[1]).write_bytes(filedata) # write data to a file
# open(sys.argv[1], 'rb').write(filedata) should work too

1 个答案:

答案 0 :(得分:1)

  

如何按原样将字符串转换为字节对象,即不对其进行编码?

不能。这是术语的矛盾-从Python 3开始。

字符串是一系列文本字符。考虑字母,标点,空格,甚至控制字符。 bytes 对象是8位数字的序列。这两个序列如何相关是一个编码问题。没有办法解决。

文本字符应被视为抽象实体。例如,字母A仅存在。没有与之相关的数字本身。 (在内部,它由Unicode代码点表示,一个数字,但这是实现的详细信息。)

在上面的代码中,您正在读取字节并且正在写入字节,并且在这两者之间您想操纵字节流:更改其中一个数字,附加其他数字。

Python bytesstr在这方面没有什么不同:它们都是不可变的类型。如果您执行了与上述相同的操作,但使用了字符串,则会得到相同的错误:

>>> s = 'abcd'
>>> s[3] = 'x'
TypeError: 'str' object does not support item assignment

也就是说,字符串不支持就地字符操作。但是,还有其他方法可以达到相同的结果。另一方面,支持就地字节操作 -可以说是因为用例比字符串更常见。您只需要使用bytearray而不是bytes

>>> data = bytearray(b'\x00\x01\x02\x03\x04')
>>> data[3] = 255
>>> print(data)
bytearray(b'\x00\x01\x02\xff\x04')

然后您可以在不使用任何编码的情况下写入文件:

pathlib.Path('result.bin').write_bytes(data)

(请注意,bytes文字必须以b为前缀。)