22

I am trying to append a string to a file, if the string doesn't exit in the file. However, opening a file with a+ option doesn't allow me to do at once, because opening the file with a+ will put the pointer to the end of the file, meaning that my search will always fail. Is there any good way to do this other than opening the file to read first, close and open again to append?

In code, apparently, below doesn't work.

file = open("fileName", "a+")

I need to do following to achieve it.

file = open("fileName", "r")
... check if a string exist in the file
file.close()

... if the string doesn't exist in the file
file = open("fileName", "a")
file.write("a string")
file.close()
3
  • 2
    what you need is the seek operation tutorialspoint.com/python/file_seek.htm Commented Feb 7, 2015 at 17:49
  • 1
    do you want to check the for a substring, a line or an actual word? Commented Feb 7, 2015 at 17:54
  • Um. In my case, a substring. Commented Feb 7, 2015 at 18:43

3 Answers 3

43

To leave the input file unchanged if needle is on any line or to append the needle at the end of the file if it is missing:

with open("filename", "r+") as file:
    for line in file:
        if needle in line:
           break
    else: # not found, we are at the eof
        file.write(needle) # append missing data

I've tested it and it works on both Python 2 (stdio-based I/O) and Python 3 (POSIX read/write-based I/O).

The code uses obscure else after a loop Python syntax. See Why does python use 'else' after for and while loops?

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

5 Comments

@glglgl: perhaps a downvoter is not familiar with the "else after a loop" syntax and they thought that I've used the indentation incorrectly.
good stuff. FIY as this was new to me; the else statement in conjunction with the for/while-loops is a concept called "completion clause" .
Thanks. I also need to create file if it does not exists. However, using "a+" on this does not work.
@Abiral: you could catch FileNotFoundError and create the new file.
Nice code. The .write() does not add a ('\n'), so I recommend file.write(needle + '\n') so its a valid text file.
8

You can set the current position of the file object using file.seek(). To jump to the beginning of a file, use

f.seek(0, os.SEEK_SET)

To jump to a file's end, use

f.seek(0, os.SEEK_END)

In your case, to check if a file contains something, and then maybe append append to the file, I'd do something like this:

import os

with open("file.txt", "r+") as f:
    line_found = any("foo" in line for line in f)
    if not line_found:
        f.seek(0, os.SEEK_END)
        f.write("yay, a new line!\n")

1 Comment

Thanks for this answer. I rearranged the contents of the file I was checking through and somehow the string I was doing the check for was getting duplicated in the file. I had to jump to the beginning of the file first using f.seek(0, os.SEEK_SET) before doing the check which is line_found in your case, then jump to the end of the file before writing to it.
2

There is a minor bug in the previous answers: often, the last line in a text file is missing an ending newline. If you do not take that that into account and blindly append some text, your text will be appended to the last line.

For safety:

needle = "Add this line if missing"
with open("filename", "r+") as file:
    ends_with_newline = True
    for line in file:
        ends_with_newline = line.endswith("\n")
        if line.rstrip("\n\r") == needle:
           break
    else: # not found, we are at the eof
        if not ends_with_newline:
            file.write("\n")
        file.write(needle + "\n") # append missing data

Comments

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.