How to create a backward moving input class in Python
<p>How to create a backward moving input class in Python? I have a class called input which reads a file forward returning one character at a time now I would like to change it to read backwards.</p>

<pre><code># Buffered input file.  Returns one character at a time.


class Input:

        def __init__( self, file ):
                self.file = file        # must open( &lt;filename&gt;, 'rb' )
                self.length = 0
                self.used = 0
                self.buffer = ""

        def read( self ):
                if self.used &lt; self.length:     # if something in buffer
                        c = self.buffer[self.used]
                        self.used += 1
                        return c

                else:
                        self.buffer = self.file.read( 2048 )  # or 2048
                        self.length = len( self.buffer )
                        if self.length == 0:
                                return -1
                        else:
                                c = self.buffer[0]
                                self.used = 1
                                return c
</code></pre>

<p>I think the only way this can work with text files in Python 3 is to read the whole text of the file in at once, and then yield characters from the end of the string you've loaded. You can't read the file in chunks starting from the end because there's no way to safely seek to an arbitrary position in the text. If you picked an arbitrary spot (e.g. 2048 bytes before the end of the file) you might land in the middle of a multi-byte character. For this reason Python doesn't support doing a <code>seek</code> to anywhere other than the start and end of the file, or to a place you've been before (and saved the position of with <code>tell</code>).</p>

<p>If your file is small enough, I'd suggest something like this:</p>

<pre><code>class ReverseInput():
    def __init__(self, file):
        buffer = file.read() # read all text
        self.rev_iter = reversed(buffer) # save a reverse iterator into the text

    def read(self):
        try:
            return next(self.rev_iter)
        except StopIteration:
            return -1  # raising an exception or returning "" might be a better API
</code></pre>

<p>If the file is too large to store in memory at once, I suppose you could work around the limitation on seeking by reading and discarding blocks of a limited size going forwards through the file and using <code>self.file.tell()</code> to save locations you can seek back to later. It would probably be slow, awkward and easy to mess up.</p>

python python-3.x