3

I am attempting to pack the contents of a python bytearray into a 4byte signed integer using struct.pack. Unfortunately, pack wants a string, so after some googling I figured I needed to decode my bytearray to a string. I figured ascii meant since because an ascii character is a byte long. Unfortunately, ascii did not want to support my values > 127, so I thought I would use replace...

but when I do this decode returns an object of type unicode and now each of my bytes is a 4 character string...

This just seems a little ridiculous, im missing something obvious (ps I have been using python for about two weeks)

here is what I am trying to do...

    val = long(-5) 
s = bytearray(pack("<i", val)) 

s.pop() # pop off msb

# write it out the way we want to then read it in the way the code does
fout = open("test.bat", "wb")
fout.write(s) 
fout.close()

fin = open("test.bat", "rb") 

inBytes = bytearray(fin.read(3))
# extend sign bit
if (inBytes[2] & 0x80):
    inBytes.append(0xff)
else:
    inBytes.append(0x00)

nb = inBytes.decode('ascii', 'replace')
# ERROR:root:after decode, len: 4 type: <type 'unicode'>
logging.error("after decode, len: {0} type: {1}".format(len(nb), type(nb)))

# struct.error: unpack requires a string argument of length 4 
inInt32 = unpack('<i', inBytes.decode('ascii', 'replace'))[0]

fin.close()

2 Answers 2

1

All you need is to cast inBytes back to str:

>>> inint = struct.unpack('<i', str(inBytes))
>>> inint
(-5,)
Sign up to request clarification or add additional context in comments.

1 Comment

-1 For Python 2.x, best to stick to str; str -> bytearray -> str is confusing. Also there's no such concept as "cast" in Python.
1

When you read from a file in binary mode, you get an object that can be used immediately with struct.unpack.

Creating the input data:

>>> import struct
>>> f = open('foo.bin', 'wb')
>>> f.write(struct.pack('<i', -5)[:3])
3
>>> f.close()

Python 2.x .. it's a str object.

>>> f = open('foo.bin', 'rb')
>>> raw = f.read()
>>> f.close()
>>> print "received", type(raw), repr(raw)
received <type 'str'> '\xfb\xff\xff'
>>> if raw[2] >= '\x80':
...     raw += '\xff'
... else:
...     raw += '\x00'
...
>>> print "extended", type(raw), repr(raw)
extended <type 'str'> '\xfb\xff\xff\xff'
>>> number = struct.unpack('<i', raw)[0]
>>> print "number", number
number -5
>>>

Python 3.x ... it's a bytes object.

>>> f = open('foo.bin', 'rb')
>>> raw = f.read()
>>> f.close()
>>> print("received", type(raw), repr(raw))
received <class 'bytes'> b'\xfb\xff\xff'
>>> if raw[2] & 0x80:
...     raw += b'\xff'
... else:
...     raw += b'\x00'
...
>>> print("extended", type(raw), repr(raw))
extended <class 'bytes'> b'\xfb\xff\xff\xff'
>>> number = struct.unpack('<i', raw)[0]
>>> print("number", number)
number -5
>>>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.