8

I have a binary file which I'm reading where some 2 byte values are stored in 'reverse' byte order (little endian?), eg.

1D 00 13 00 27  00 3B 00 45  00 31 00 4F

The original program that created these values stores them internally as shorts. Those values should correspond to: 29, 19, 39, 59, 69, 49, 79. I'm trying to read these values using python 2.6.5 (although this will probably be run on much older systems, eg 2.3 and 2.4).

I've tried using

val1, val2, val3, val4, val5, val6, val7 = struct.unpack("1h 1h 1h 1h 1h 1h 1h", data)

and, of course, the values all come out wrong:

7427
4864
9984
15104
17664
12544
20224

After looking at the documentation for struct, I thought I'd be able to use something like

val1, ... = struct.unpack("!h !h ...

but when testing, I only got

struct.error: bad char in struct format

How can I unpack these values with the correct byte ordering? Am I stuck reading in the two bytes separately then reassembling them in the python code?

pfyon
  • 332
  • 1
  • 6
  • 10

3 Answers3

10

Byte order is specified with a single character, at the beginning of the format string.

values = struct.unpack('!7h', data)
Cat Plus Plus
  • 125,936
  • 27
  • 200
  • 224
  • Aha, that was it. I have several format specifiers in the format string but only placed the byte order char in front of the 'h' specifier instead of at the start of the whole string. Thanks! – pfyon Nov 02 '11 at 17:55
4

How about

>>> a='\x1d\x00\x13\x00\x27\x00\x3b\x00\x45\x00\x31\x00\x4f\x00'

>>> struct.unpack('<%dH' % (len(a) / 2), a)

(29, 19, 39, 59, 69, 49, 79)?

According to the struct documentation it looks like you need to use < to specify little-endian.

1

I have solved a similar problem of reversed byte order by using a.byteswap(True), but I am not sure if this is the most efficient method.

captain_M
  • 287
  • 2
  • 10