2013-06-27 45 views
0

我正在写一个应用程序将二进制数据(整数,双精度,原始字节)写入文件。Python mangles struct.pack字符串写入磁盘

问题是,这些数据是不实际写入文件我希望它是方式:

>>> 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

回答

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代替。

+0

'hexdump -C' returns'00000000 00 00 00 01 | .... |',是的,它看起来像'hexdump'的默认模式是“破碎”。 –

1

这里的问题不是用python,而是用hexdump。它将文件中的数据视为16位小端值。你需要做的是告诉hexdump将数据视为8位值。不考虑它,我认为这是'-c'选项。

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