0

If I have a binary file, I can open it in mode rb and move the pointer with .seek():

with open(fname, "rb") as fid:
    fid.seek(101)

But this is not possible with a bytearray:bytearray(10).seek(1).


Does a bytearray which supports seek exist?

I have 2 almost identical code snippets reading data from a binary file/buffer that I would like to merge, one reading from a binary file and one from a byte array. The reading operation is done with numpy, with either numpy.fromfile or numpy.frombuffer. Both accept an argument offset to control the pointer position, but in a slightly different manner. fromfile defines the offset from the current position while frombuffer defines the offset from the beginning of the buffer.

Any idea on which object I could use instead of bytearray to be able to run the same reader code snippet on either an opened binary file fid or on a bytearray-like buffer?

Mathieu
  • 5,410
  • 6
  • 28
  • 55

1 Answers1

0

I think the easiest thing to do there is to subclass bytearray, and just add the seek, tell, read and write methods - it will work just like a bytearray for everything else, and can be used most places file-like objects are expected:

import os

class B(bytearray):
    def __init__(self, *args, size=None):
        if not args and size:
            args = (b"\x00" * size,)
        super().__init__(*args)
        self.cursor = 0
    def tell(self):
        return self.cursor
    def seek(self, position, from_where=os.SEEK_SET):
        if from_where == os.SEEK_SET:
            self.cursor = position
        elif from_where == os.SEEK_CUR:
            self.cursor += position
        elif from_where == os.SEEK_END:
            self.cursor = len(self) - position
        return self.cursor
    def read(self, amount):
        return self[self.cursor: self.cursor + amount]
    def write(self, data):
        self[self.cursor: self.cursor + (amount:=len(data))] = data
        return amount

And, using this in the interactive mode:

In [227]: b = B(4096)

In [228]: b.seek(100)
Out[228]: 100

In [229]: b.seek(100, os.SEEK_CUR)
Out[229]: 200

In [230]: b.write(b"Hello World!")
12

In [231]: b[200: 212].decode()
Out[231]: 'Hello World!'
jsbueno
  • 99,910
  • 10
  • 151
  • 209