我正在开发一个将二进制数据(整数,双精度,原始字节)写入文件的应用程序。
问题是,数据实际上并没有按照我预期的方式写入文件:
>>> import struct
>>> import io
>>> out = io.open("123.bin", "wb+")
>>> format = "!i"
>>> data = struct.pack(format, 1)
>>> out.write(data)
4L
>>> data
'\x00\x00\x00\x01'
>>> out.close()
>>> infile = io.open("123.bin", "rb")
>>> instr = infile.read()
>>> instr
'\x00\x00\x00\x01'
>>> struct.unpack("!I", instr)
(1,)
所以一切看起来都很好。但经过仔细研究,123.bin
文件包含以下内容:
$ hexdump 123.bin
0000000 0000 0100
0000004
所以看起来字节是由io.write()
交换的!
python文档说,io.write()
接受“给定的字节或bytearray对象”,问题是,struct.pack
确实返回str
:
>>> type(struct.pack(format, 1))
<type 'str'>
那么,我做错了什么?如何在没有任何字符集翻译的情况下将str
转换为bytes
?
答案 0 :(得分:4)
看起来这是hexdump(1)
的奇怪之处。使用xxd(1)
,我得到......
$ xxd 123.bin
0000000: 0000 0001 ....
......看起来不错。
您似乎必须使用-C
选项才能以合理的格式输出hexdump(1)
...
$ hexdump -C 123.bin
00000000 00 00 00 01 |....|
00000004
...或者将其称为hd
。
答案 1 :(得分:1)
这里的问题不是python,而是hexdump。它将文件中的数据视为16位小端值。您需要做的是告诉hexdump将数据视为8位值。没有查找,我认为这是'-c'选项。
答案 2 :(得分:1)
hexdump
的默认输出格式与使用-x
选项相同,即根据手册页:
-x Two-byte hexadecimal display. Display the input offset in hexadecimal,
followed by eight, space separated, four column, zero-filled, two-byte
quantities of input data, in hexadecimal, per line.
hexdump
使用的字节序是架构字节序(这里可能是little-endian),而你要求python以网络顺序存储值(big-endian)。
因此,该值已正确存储,但hexdump
错误地解释了该值。您可以使用-C
选项或xxd
代替hexdump
。
$ hexdump 123.bin
0000000 0000 0100
0000004
$ hexdump -C 123.bin
00000000 00 00 00 01 |....|
00000004