francisco
francisco

Reputation: 37

When writing to a file, can you be specific about where you want to write?

I have a text file, which has the following:

    20
    15
    10

And I have the following code:

    test_file = open("test.txt","r")
    n = 21
    line1 = test_file.readline(1)
    line2 = test_file.readline(2)
    line3 = test_file.readline(3)
    test_file.close()
    line1 = int(line1)
    line2 = int(line2)
    line3 = int(line3)
    test_file = open("test.txt","a")
    if n > line1:
        test_file.write("\n")
        n = str(n)
        test_file.write(n)
        test_file.close()

This code checks if the variable 'n' is bigger than line 1. What I wanted it to do is if it is bigger than line 1, it should be written in a line before the previous line 1. However this code will write it at the bottom of the file. Is there anything I can do to write something where I want to and not at the bottom of the file? Any help is appreciated.

Upvotes: 1

Views: 106

Answers (2)

Pitto
Pitto

Reputation: 8579

As correctly pointed out by Amadan in a comment, the only way to obtain this result is a complete rewrite of the file. This, clearly depending on how strict your requirements are, is fairly inefficient.

If you want to understand more about inefficiency just imagine the actions you would have to manually take to write a new 1st line in a physical notebook page.

Since the 1st line is already written you would have to turn the page, write the new first line, then copy again all the lines from the old page and, finally, tear the 1st page out and have your perfect notebook with a perfect page again.

You are writing with pen so there is no possibility to delete, only a new page will do the trick.

That is quite some work! This is - well, more or less - what Python is doing behind the scenes when it is opening for reading (the 'r' part in my examples below) and then opening for writing (the 'w' part) the same file again.

As a general idea imagine that when you see for loops there is a lot of work to do.
I will clumsily over-simplify saying that the more the for loops the slower the code (countless pages of paper have been written by brilliant minds on performances, I suggest you diving dive deeper and searching for "Big O notation" using your preferred search engine. Here's an example: https://www.freecodecamp.org/news/all-you-need-to-know-about-big-o-notation-to-crack-your-next-coding-interview-9d575e7eec4/).

A better solution would be to change your data file and make sure that the last value is also the most recent one.

Rewriting the file is as easy as writing an empty file, code and result are identical.
The trick here is that we have in memory (in the variables data and new_data) everything we need.

In data we store the whole content of the file before the change. In new_data we can easily apply the needed modification because it is just a list containing a number and a newline (\n) for each list item.

Once new_data contains the data in the desired order all we need to do is write that list into a file.

Here's a possible solution, as close as possible to your code:

n = 21

with open('test.txt', 'r') as file:
    data = file.readlines()

first_entry = int(data[0])

if (n > first_entry):
    new_data = []
    new_value = str(n) + "\n"
    new_data.append(new_value)
    for item in data:
        new_data.append(item)
    with open('test.txt', 'w') as file:
        file.writelines(new_data)

Here's a more portable one:

def prepend_to_file_if_bigger_than_first_line(filename, value):
    """Checks if value is bigger than the one found in the 1st line of the specified file,
       if true prepends it to the file

        Args:
        filename (str): The file name to check.
        value    (str): The value to check.
    """
    with open(filename, 'r') as file:
        data = file.readlines()
    first_entry = int(data[0])
    if (value > first_entry):
        new_value = "{}\n".format(value)
        new_data = []        
        new_data.append(new_value)
        for old_value in data:
            new_data.append(old_value)
        with open(filename, 'w') as file:
            file.writelines(new_data)

prepend_to_file_if_bigger_than_first_line("test.txt", 301)

As bonus some food for thought and exercises to learn:

  • What if instead of rewriting everything you just add a new line to the end of the page? Wouldn't it be more efficient and effective?
  • How would you re-implement my function above just to check the last line in file and append a new value?
  • Try bench-marking the prepend and the append solution, which one is best?

Upvotes: 2

moe asal
moe asal

Reputation: 582

You can put your whole data in a variable, edit that variable then overwrite the information in the file.

with open('test.txt', 'r') as file:
    # read a list of lines into data
    data = file.readlines()

# now change the 2nd line, note that you have to add a newline
data[1] = "42\t\n" 

# and write everything back
with open('test.txt', 'w') as file:
    file.writelines( data )

This is a short answer, implement your own algorithm to solve your own problem.

Upvotes: 2

Related Questions