Reading a binary file
p-abel at t-online.de
Thu Jun 26 23:52:50 CEST 2003
Sorin Marti <mas at semafor.ch> wrote in message news:<mailman.1056637113.19927.python-list at python.org>...
> Peter Hansen wrote:
> > Sorin Marti wrote:
> >>I am quite new to python and very new to this list.
> >>I've got following problem. I have a binary file which contains
> >>information I should read. I can open the file with
> > [snip]
> > It would really be best if you could describe in more detail
> > what you are trying to do with this data. Bytes are bytes,
> > and things like hex and binary are just different _representations_
> > of bytes, so whether you want binary, hex, decimal, or something
> > else depends entirely on the use to which you will put the info.
> Hi Peter,
> Ok I'll try to give more details. I have a Siemens SPS. With an SPS you
> can controll machines such as pumps or motors or anything else. To
> controll you have to set Variables. If you want to see which state these
> variables have you can get a file via ftp where these values are stored.
> This is what I have done. Now I have a file (called cpu1db2.dat) and
> this file has a length of 16 bytes.
> Byte Number/Length Type Hex-Value
> Byte 1: Boolean: 01 (which is true, 00 would be false)
> Byte 2: Byte: 11 (This data type is called byte)
> Byte 3: Char: 50 (Which should be a "P")
> Byte 4,5: Word 00 00
> Byte 6,7: Integer 22 04
> Byte 8,9,10,11: DoubleWord D2 00 00 BB
> Byte 12,13,14,15,16: Real BB 42 C8 00 00
As some others described the struct module should do the right work:
>>> import struct
### This should be your data to read from a file into a string x.
### The format to decode your data except the Real.
### The **>** is necessary because your data come little-endian.
... Boolean : %02X
... Byte : %02X
... Char : %s
... Word : %04X
... Integer : %04X
... DoubleWord: %04X"""
>>> print format%(Boolean,Byte,Char,Word,Integer,DoubleWord)
Boolean : 01
Byte : 11
Char : P
Word : 0000
Integer : 2204
> So I have written a python class which makes a connection to the
> ftp-server (on the SPS) and gets the file.
> Then there is a function where you can call a value with a startbyte and
> an endbyte. You also have to specify the type. That means you can call
> getValue('REAL',12,16) and you should get back 100 because if you have
I guess your Real is a 4-Byte Realvalue and you meant: '42 C8 00 00'
what is the value of your binary representation.
> the binary value of 'BB 42 C8 00 00' is 01000010110010000000000000000000
> , first digit is the Sign (which is + or - ), next 8 digits are the
> exponent, in this case 10000101 = 133dec. Now you take away 127 from 133
> then you get six, thats the exponent. The rest
> (110010000000000000000000) has a hex value of C80000 this is 13107200
> decimal. Now you have to multiply 13107200 with 2^6 and 2^-23 and you
> get (tataaaaaa!): 100!
I'm not quite sure if I understand the format your're describing above.
I dealed some time ago with IEEE and some AMD FPU-Format but you seem
to me to describe a format where the exponent goes over Bytelimits.
A function could be somewhat as the following:
>>> def str2real(s):
... sign = ord(s)&0x80 and -1 or 1
... expo = ((ord(s)&0x7f)<<1) + (ord(s)>>7) - 127
... mantissa = ((ord(s)<<16)|0x80) + (ord(s)<<8) + ord(s)
... print 'sign=%d, expo=%d, mantissa=%06X'%(sign,expo,mantissa)
... return sign*2**(expo-23)*mantissa
sign=1, expo=6, mantissa=C80080
Thoug I'm not sure if I hit the goal, cause normally the exponent is
in 6 or 7 or 8 Bits 2's complement and then there would be a - 64 or
- 128 or - 256 instead of - 127 in the algo. Also a 23 Bit mantissa
seems a bit strange to me. Even if so the 24rth Bit is **1**
by default, why I put **|0x80**.
With an excact description of your Real-Format the solution would
be a "Klacks".
> The different data types need different calculations, that's why I asked
> a few things about changing the representation because I only can do
> some things in binary mode or hex mode.
> Sorin Marti
More information about the Python-list