user3702643
user3702643

Reputation: 1495

Check if value exists in file

I am trying to read the following file line by line and check if a value exists in the file. What I am trying currently is not working. What am I doing wrong?

If the value exists I do nothing. If it does not then I write it to the file.

file.txt:

123
345
234
556
654
654

Code:

file = open("file.txt", "a+")
lines = file.readlines()
value = '345'
if value in lines:
    print('val ready exists in file')
else:
    # write to file
    file.write(value)

Upvotes: 10

Views: 6872

Answers (8)

Meet Daxini
Meet Daxini

Reputation: 46

When you are opening file in "a+" mode the file cursor from where the readlines() method will start reading will be at the end so readlines would read nothing. You need to do f.seek(0) in order to move the cursor to the beginning.

file = open("file.txt", "a+")
file.seek(0)
lines = [line.strip() for line in file.readlines()]
print(lines)

value = '345'
if value in lines:
    print('val ready exists in file')
else:
    print("else")
    # write to file
    file.write(value)
file.close()

Upvotes: 2

Saelyth
Saelyth

Reputation: 1734

I would consider several changes.

1: Use with to automatically close the file.
2: Use strip() to remove leading or trailing stuff, like \n
3: Use a break for the loop.
4: Add \n in the write part.

value = "345"
with open("file.txt", "a+") as file:
    file.seek(0)
    for line in file.readlines():
        if line.strip("\n") == value:
            print('val ready exists in file')
            break
    else:
        # write to file
        file.write(f"\n{value}")

Upvotes: 6

RoadRunner
RoadRunner

Reputation: 26315

Since you want to open the file for reading and writing, I suggest using the r+ mode from open(). This will open the file at the beginning of the file, since we want to first read all lines. Using a+ will open the file for reading and writing at the end of the file, which will cause lines to give you an empty list from readlines().

You also need to strip newlines from lines before checking if the value exists. This is because 345 is not equal to 345/n. We can use a list comprehension to strip the newlines from lines using str.rstrip(), which strips whitespace from the right. Additionally, If you have to do repetitive lookups for multiple values, it might be worth converting lines to a set for constant time lookups, instead of doing a linear search with a list.

Its also worth using With Statement Context Managers when reading files, since the closing of the file is handled for you.

value = '345'

with open("file.txt", mode="r+") as file:
    lines = [line.rstrip() for line in file.readlines()]

    if value in lines:
        print('value ready exists in file')
    else:
        file.write(f"{value}\n")

The other choice is to use f.seek(0) with a+ to set the position at the beginning of the file, as shown in @Cihan Ceyhan's answer. However I think this overcomplicates things, and its just easier to use the r+ mode.

Upvotes: 3

Jaydip Pawar
Jaydip Pawar

Reputation: 135

The readlines() method returns a list containing \n with each element so when the condition is checked it is not compared with value with \n so the statement is always false so i have a code that solve your problem.

f_name = "file.txt"
text = "102"
def check_in_file(file_name, value):
    with open(file_name, 'r') as read_obj:
        for line in read_obj:
            if value in line:
                return True
    return False
if check_in_file(f_name, text):
    print('Yes, string found in file')
else:
    print('String not found in file')
    file = open(f_name, 'a')
    file.write("\n"+text)
    file.close()

Upvotes: 1

Cihan
Cihan

Reputation: 2307

There are two problems here:

  • .readlines() returns lines with \n not trimmed, so your check will not work properly.
  • a+ mode opens a file with position set to the end of the file. So your readlines() currently returns an empty list!

Here is a direct fixed version of your code, also adding context manager to auto-close the file

value = '345'
with open("file.txt", "a+") as file:
    file.seek(0) # set position to start of file
    lines = file.read().splitlines() # now we won't have those newlines
    if value in lines:
        print('val ready exists in file')
    else:
        # write to file
        file.write(value + "\n") # in append mode writes will always go to the end, so no need to seek() here

However, I agree with @RoadRunner that better is to just use r+ mode; then you don't need the seek(0). But the cleanest is just to split out your read and write phases completely, so you don't run into file position problems.

Upvotes: 12

AdamF
AdamF

Reputation: 2940

when working with io the recomended approach is to use the context manager. Context managers allow you to allocate and release resources precisely when you want to. The most widely used example of context managers is the with statement. if you have a large file better not to use file.readlines() or the read() method. The readlines() method returns a list containing each line in the file as a list item. better to iterate on the file stream line by line (generator). always use try except with io operations! :

values=['123','233'...]
try:
    with open("file.txt", "r+") as fp:
        for line in fp:
            for val in values:
                if val not in line.strip():
                    fp.write(val)
                else:
                    print('val ready exists in file')
except (OSError,...): #catch what ever you think this code above can raise, and re raise in except block if you want.
#do exception handling

Upvotes: 3

Michal Patyjewicz
Michal Patyjewicz

Reputation: 65

This should work :)

filename = 'file.txt'
value = '345'

with open(filename) as f:
    if value in f.read(): # read if value is in file 
        print('Value is in the file')

This will check if the value is in the file and if it's not there. It will add value to the file.

filename = 'file_1.txt'
value = '999'

with open(filename, 'r+') as f:
    if value in f.read():
        print(f"Value {value} is in the file")
    else:
        print("The value not in the file.\nTherefore, saving the value in the file.")
        f.write(f"{value}\n")

Upvotes: 2

Afsana Khan
Afsana Khan

Reputation: 122

Your python script works for me properly. I guess the last line in the else statement should be file.write(value) instead of file.write(val).

Upvotes: 1

Related Questions