2

I would like to specify a raw_input command to delete the last line of the txt file while appending the txt file.

Simple code:

while True:
    userInput = raw_input("Data > ")
    DB = open('Database.txt', 'a')
    if userInput == "Undo":
        ""Delete last line command here""
    else:
        DB.write(userInput)
        DB.close()

1 Answer 1

1

You can't open a file in append mode and read from it / modify the previous lines in the file. You'll have to do something like this:

import os

def peek(f):
        off = f.tell()
        byte = f.read(1)
        f.seek(off, os.SEEK_SET)

        return byte

with open("database.txt", "r+") as DB:
        # Go to the end of file.
        DB.seek(0, 2)

        while True:
                action = raw_input("Data > ")

                if action == "undo":
                        # Skip over the very last "\n" because it's the end of the last action.
                        DB.seek(-2, os.SEEK_END)

                        # Go backwards through the file to find the last "\n".
                        while peek(DB) != "\n":
                                DB.seek(-1, os.SEEK_CUR)

                        # Remove the last entry from the store.
                        DB.seek(1, os.SEEK_CUR)
                        DB.truncate()
                else:
                        # Add the action as a new entry.
                        DB.write(action + "\n")

EDIT: Thanks to Steve Jessop for suggesting doing a backwards search through the file rather than storing the file state and serialising it.

You should note that this code is very racy if you have more than one of this process running (since writes to the file while seeking backwards will break the file). However, it should be noted that you can't really fix this (because the act of removing the last line in a file is a fundamentally racy thing to do).

Sign up to request clarification or add additional context in comments.

4 Comments

If you can be bothered, you can seek to the correct place in the file and truncate there, rather than truncating at 0 and re-writing the whole file. Let us suppose it to be 200GB in size ;-). Searching backwards through a file for a linebreak is kind of tedious, but if the tail Unix command can do it, so can we.
Yes, but tail is broken by design: youtu.be/vm1GJMp0QN4?t=2475. And I'd really hope nobody uses a system like this for a 200GB file (do you have 200GB of virtual memory on tap?) :P
you already say that there shouldn't be two things truncating at once, this merely says there shouldn't be a tail -f on it either :-)
There, I've changed it so we do a backwards seek through the file.

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.