Seite 1 von 1

struct.unpack() mit Pascal-Strings

Verfasst: Mittwoch 1. Oktober 2003, 12:51
von Jens Meyer
Hallo,

Hat einer der Mitleser vielleicht schon mal versucht Strukturen mit
Pascal-Strings einzulesen? Ich komme da einfach nicht weiter.
Folgendes hab ich probiert:

>>> from struct import *
>>>test=unpack('pp', '\x02\x30\x31\x02\x32\x33')

und raus kommt:

Traceback (most recent call last):
File "<stdin>", line 1, in ?
struct.error: unpack str size does not match format

Kann mir einer einen Tip geben was ich da falsch mache?
Ich hab da schon verschiedene Varianten ausprobiert und
auch im Web rumgesucht, aber im Moment komme ich da einfach
nicht weiter.

Jens

Verfasst: Mittwoch 1. Oktober 2003, 13:08
von Dookie
Hi Jens,

ist etwas trickly, du musst im Fomatstring auch die Länge der Strings angeben, einschliesslich des Längenbytes am Anfang.

Code: Alles auswählen

>>> test=unpack('3p3p', "\x02\x30\x31\x02\x32\x33")
>>> print test
('01', '23')

Gruß

Dookie

Verfasst: Mittwoch 1. Oktober 2003, 13:14
von Jens Meyer
Hi Dookie,

Heisst das, das ich schon vorher wissen muss wie lang die Strings
in der Struktur sind? Da kann man das zerlegen dann ja fast schon
zu Fuss erledigen wenn ich das vorher rauslesen muss.
Ich hab hier das Problem, das ich eine Datei mit einer ziemlich grossen
Struktur einlesen will, die halt Pascal-Strings enthaelt und deswegen
auch unterschiedlich lang sein kann. Wenn das oben gesagte stimmt
hilft mir da struct.unpack nicht gerade weiter.

Jens

Verfasst: Mittwoch 1. Oktober 2003, 14:16
von Dookie
naja, etwas einfacher ist die Verwendung von struct schon.
Hier eine Routine speziell für pascalstrings

Code: Alles auswählen

import struct

def punpack(pstrings):
    f = ""
    i = 0:
    while i < len(pstrings):
        n = ord(pstring[i])+1
        f += "%ip" % n
        i += n
    return struct.unpack(f,pstrings)
Dookie

Verfasst: Mittwoch 1. Oktober 2003, 16:08
von Jens Meyer
Danke Dookie,

Ich hatte in der Zwischenzeit schon mal etwas ausprobiert, siehe unten.
Das hat den Vorteil, das ich die Bezeichner aus der vorliegenden
Strukturbeschreibung 1:1 uebernehmen kann (U1, U2,...) und sogar
gleich ein Dictionary mit den einzelnen Werten und dem Feldnamen als
Schluessel zurueckbekomme (auch wenn das merkwuerdigerweise
gegenueber der Definition umsortiert ist, egal).

Jens

Code: Alles auswählen

FAR_Description = (("U1", "CPU_TYPE"),\
                            ("U1", "STDF_VER")\
                            ("Cn", "STDF_NAME")\
                            )

def stripstructure(data, descr):
    resultdata = {}
    index = 0
    for element in descr:
        if (index >= len(data)):
            break

        if (element[0] == "U1"):
            resultdata[element[1]] = unpack("!B", data[index])[0]
            index += 1

        elif (element[0] == "U2"):
            resultdata[element[1]] = unpack("!H", data[index:index+2])[0]
            index += 2

        elif (element[0] == "U4"):
            resultdata[element[1]] = unpack("!L", data[index:index+4])[0]
            index += 4

        if (element[0] == "I1"):
            resultdata[element[1]] = unpack("!b", data[index])[0]
            index += 1

        elif (element[0] == "I2"):
            resultdata[element[1]] = unpack("!h", data[index:index+2])[0]
            index += 2

        elif (element[0] == "I4"):
            resultdata[element[1]] = unpack("!l", data[index:index+4])[0]
            index += 4

        elif (element[0] == "R4"):
            resultdata[element[1]] = unpack("!f", data[index:index+4])[0]
            index += 4

        elif (element[0] == "R8"):
            resultdata[element[1]] = unpack("!d", data[index:index+8])[0]
            index += 4

        elif (element[0] == "C1"):
            resultdata[element[1]] = data[index + 1]
            index += 1

        elif (element[0] == "Cn"):
            strlength = ord(data[index])
            index += 1

            if (strlength > 0):
                resultdata[element[1]] = data[index:index+strlength]
            else:
                resultdata[element[1]] = ""
            index += strlength

    return(resultdata)

  :
  :
readbuffer=fd.read(structsize)
FAR_Data = stripstructure(readbuffer, FAR_Description)

print FAR_Data["CPU_TYPE"]
  :
  :