File-like Strings in Python

Sometimes one has data stored in a string, and wishes to pass that data to a function that expects a file-like object. Writing the data to a file, then opening that file and passing it to the function is cumbersome and seems inefficient. A better solution is to turn the string into a file-like object, and pass it directly to the function.

Motivation

I was extracting some images from an Flash (SWF) file, and ended up with the bytes of a JPG file in a string buffer. (The bytes had to be massaged after being read from the SWF file.) I wanted to invoke the Image.open() function of the Python Imaging Library (PIL), but that function requires a filename or a file-like object as an argument. I didn’t see any immediate alternatives to Image.open(), as Image.fromstring() didn’t seem to do what I wanted. I also didn’t want to have to write the data to a file, just to have PIL read it back in to memory.

Climbing the Wall Next to the Elevator

I beetled off and implemented the following class, which supports the read(), tell(), and seek() functions that Image.open() requires.

class FileString(object):
    def __init__(self, buffer):
        self.pos    = 0
        self.buffer = buffer

    def read(self, size=None):
        if (size == None):
            size = len(self.buffer) - self.pos
        if (size <= 0):
            return ''
        rv = self.buffer[self.pos:self.pos+size]
        self.pos += size
        return rv

    def tell(self):
        return self.pos

    def seek(self, offset, whence=0):
        if (whence == 0):
            self.pos = offset
        elif (whence == 1):
            self.pos += offset
        elif (whence == 2):
            self.pos = self.size + offset

Overall, I think it’s a pretty decent implementation of a simple idea. However….

Embarassment

While writing up this post, I found the StringIO class, which does exactly what I need, and is, uhm, built-in to Python. Whoops. I suppose this is one of those occasions when the subtitle of this blog (“Making mistakes so you don’t have to”) is particularly apropos. Anyway, StringIO is cool, enjoy it and happy coding.

Share and Enjoy:
  • Twitter
  • Facebook
  • Digg
  • Reddit
  • HackerNews
  • del.icio.us
  • Google Bookmarks
  • Slashdot
This entry was posted in The Hard Way. Bookmark the permalink.

Comments are closed.