struct.unpack() mit Pascal-Strings

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
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
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

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
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
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

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
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"]
  :
  :

Antworten