3

So I have the string john. I pack it into a struct. When I unpack it, how can I print john? Currently it only prints j. Same thing if I changed the string to Sammy or other names with different lengths? I have 2 functions to pack and unpack the struct. This what I don't need to worry about the lengths of the first_name's. The function can do it for me.

The structure is basically

  • user_id (in this case 1)
  • first_name (a person first name. This string can be of different lengths. In this case john)

My Code

from struct import *

def make_struct(user_id, first_name):
    return pack("is", user_id, first_name)

def deconstruct_struct(structure):
    return unpack("is", structure)

packed = make_struct(1, "john")
unpacked = deconstruct_struct(packed)

print(unpacked[1])

Current output is:

j
Mary
  • 127
  • 1
  • 6

1 Answers1

3

You need to add the length of the string to the format string:

packed = pack("i4s", 1, "john")
unpacked = unpack("i4s", packed)
print(unpacked[1])
>> john

If you need a string of variable length -> packing and unpacking variable length array/string using the struct module in python

EDIT:

Your solution can be extended like this:

from struct import *

def make_struct(user_id, first_name):
    first_name_length = len(first_name)
    fmt = "ii{}s".format(first_name_length) #generate format string with length of first_name
    return pack(fmt, user_id, first_name_length, first_name) #add the length to the pack

def deconstruct_struct(structure):
    user_id, first_name_length = unpack("ii", structure[:8]) #extract only userid and length from the pack
    fmt = "ii{}s".format(first_name_length) #generate the format string like above
    #return unpack(fmt, structure) #this would return a (user_id, length of first name, first_name) tuple
    return (user_id, unpack(fmt, structure)[2]) #this way, we return only the (user_id, first_name) tuple

packed = make_struct(1, "john")
unpacked = deconstruct_struct(packed)
Reductio
  • 429
  • 2
  • 8
  • Is there a way to automate this? Because sure, I can put `4` when I pack it. However, when I unpack it, how will I know it was 4? I want to have a dynamic struct which can handle almost any length of string. The url you linked, I sort of don't understand it. – Mary Apr 22 '19 at 00:33
  • Please have a look at the link i posted below the code. The variable length problem is addressed there. It's for python3 but should also work for python2 -> https://stackoverflow.com/questions/3753589/packing-and-unpacking-variable-length-array-string-using-the-struct-module-in-py – Reductio Apr 22 '19 at 00:44
  • The one under it using a different module. Is it possible for you to show me using this `struct` module? – Mary Apr 22 '19 at 00:56
  • I have a question. fmt is the format string like `i4s`. However, in the first line of the `deconstruct_struct` function you extract the first 8 bytes. But the `fmt` is a string, and `fmt` is a string. You extract the first 8 bytes, but you don't know the length of the fmt? what if the first name is 10,000 characters. You also pack the fmt. Is this a typo? Maybe u aren't suppose to pack the fmt? – Mary Apr 22 '19 at 01:22
  • pack creates an output string that contains the serialized data you packed. So yes, I unpack the first 8 bytes. These are the user_id (first 4 bytes) and the length of the name (next 4 bytes). From this point on, we know how long the string is and can generate the real needed fmt for the unpack. So it doesn't matter how long first name is, it will always work. – Reductio Apr 22 '19 at 01:27
  • No, there is no typo. "fmt" is never packed. It's just the first parameter of pack which describes what pack should do. And here it is dynamically created, but never packed into the data. – Reductio Apr 22 '19 at 01:34