Python 编写二进制文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20955543/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 21:38:28  来源:igfitidea点击:

Python writing binary

pythonfilepython-3.xbinary

提问by Alon

I use python 3 I tried to write binary to file I use r+b.

我使用 python 3 我试图将二进制文件写入我使用 r+b 的文件。

for bit in binary:
    fileout.write(bit)

where binary is a list that contain numbers. How do I write this to file in binary?

其中 binary 是一个包含数字的列表。如何将其写入二进制文件?

The end file have to look like b' x07\x08\x07\

最终文件必须看起来像 b' x07\x08\x07\

Thanks

谢谢

采纳答案by poke

When you open a file in binary mode, then you are essentially working with the bytestype. So when you write to the file, you need to pass a bytesobject, and when you read from it, you get a bytesobject. In contrast, when opening the file in text mode, you are working with strobjects.

当您以二进制模式打开文件时,您实际上是在使用该bytes类型。所以当你写入文件时,你需要传递一个bytes对象,当你读取它时,你会得到一个bytes对象。相反,在文本模式下打开文件时,您正在处理str对象。

So, writing “binary” is really writing a bytes string:

所以,写“二进制”实际上是写一个字节字符串:

with open(fileName, 'br+') as f:
    f.write(b'\x07\x08\x07')

If you have actual integers you want to write as binary, you can use the bytesfunction to convert a sequence of integers into a bytes object:

如果您想将实际整数写为二进制,则可以使用该bytes函数将整数序列转换为字节对象:

>>> lst = [7, 8, 7]
>>> bytes(lst)
b'\x07\x08\x07'

Combining this, you can write a sequence of integers as a bytes object into a file opened in binary mode.

结合这一点,您可以将整数序列作为字节对象写入以二进制模式打开的文件中。



As Hyperboreus pointed out in the comments, byteswill only accept a sequence of numbers that actually fit in a byte, i.e. numbers between 0 and 255. If you want to store arbitrary (positive) integers in the way they are, without having to bother about knowing their exact size (which is required for struct), then you can easily write a helper function which splits those numbers up into separate bytes:

正如 Hyperboreus 在评论中指出的那样,bytes将只接受实际适合一个字节的数字序列,即 0 到 255 之间的数字。如果您想以它们的方式存储任意(正)整数,而不必担心知道它们的确切大小(结构所需),那么您可以轻松编写一个辅助函数,将这些数字拆分为单独的字节:

def splitNumber (num):
    lst = []
    while num > 0:
        lst.append(num & 0xFF)
        num >>= 8
    return lst[::-1]

bytes(splitNumber(12345678901234567890))
# b'\xabT\xa9\x8c\xeb\x1f\n\xd2'

So if you have a list of numbers, you can easily iterate over them and write each into the file; if you want to extract the numbers individually later you probably want to add something that keeps track of which individual bytes belong to which numbers.

因此,如果您有一个数字列表,您可以轻松地遍历它们并将每个数字写入文件;如果您想稍后单独提取数字,您可能需要添加一些内容来跟踪哪些单个字节属于哪些数字。

with open(fileName, 'br+') as f:
    for number in numbers:
        f.write(bytes(splitNumber(number)))

回答by Hyperboreus

where binary is a list that contain numbers

其中 binary 是一个包含数字的列表

A number can have one thousand and one different binary representations (endianess, width, 1-complement, 2-complement, floats of different precision, etc). So first you have to decide in which representation you want to store your numbers. Then you can use the structmodule to do so.

一个数字可以有一千零一种不同的二进制表示(字节序、宽度、1-补码、2-补码、不同精度的浮点数等)。因此,首先您必须决定要以哪种表示形式存储您的数字。然后你可以使用struct模块来做到这一点。

For example the byte sequence 0x3480 can be interpreted as 32820 (little-endian unsigned short), or -32716 (little-endian signed short) or 13440 (big-endian short).

例如,字节序列 0x3480 可以解释为 32820(little-endian unsigned short),或 -32716(little-endian signed short)或 13440(big-endian short)。

Small example:

小例子:

#! /usr/bin/python3

import struct

binary = [1234, 5678, -9012, -3456]
with open('out.bin', 'wb') as f:
    for b in binary:
        f.write(struct.pack('h', b)) #or whatever format you need

with open('out.bin', 'rb') as f:
    content = f.read()
    for b in content:
        print(b)
    print(struct.unpack('hhhh', content)) #same format as above

prints

印刷

210
4
46
22
204
220
128
242
(1234, 5678, -9012, -3456)