March 11, 2012

Problems with reading and searching thru txt file with PHP

Question by andreicek

I am writing a small script which checks if a users has his username in file called whitelist.txt or not. If the username is not found its added. This is the script:

$fh = @fopen("whitelist.txt", 'a+');
$stringData = $_POST[usr]. "n";
if ($fh)
    {
        while (!feof($fh))
        {
            $buffer = fgets($fh);
            if (strpos($buffer, $stringData) == TRUE)
                echo "This username is already whitelisted.";
            elseif (strpos($buffer, $stringData) == FALSE) {
                    fwrite($fh, $stringData);
                    echo "Username ". $stringData. " is now whitelisted.";
                    }
        }
        fclose($fh);
    }

What I get now if I enter a new username first time, all is ok. The second time I enter a new username it gets dubbled. Problems go on: if I enter an existing username it gets added twice and the message “This username is already whitelisted.” is not shown. Every username is in a new row.

Thank you for your time and help!

Answer by marramgrass

EDIT TO ADD: The accepted answer is great. As a counterpoint, I’ve modified your code below in the event that you want to continue to read line by line instead of all it once – the file is unlikely to get so big that doing it in one chunk is ever a problem, but making that kind of assumption always makes me very slightly nervous.


I see a couple of issues, here:

Even when you find the username in the file, you carry on through the rest of the file, getting false negatives. Try:

if (strpos($buffer, $stringData) == TRUE) {
    echo "This username is already whitelisted.";
    break;
}

Your else if will trigger whenever the script finds a line that doesn’t match the submitted username, rather than when it gets to the end of the file. You’ll need to move that check outside of the loop so that the new username is only added once. Altogether, now:

$fh = @fopen("whitelist.txt", 'a+');
$stringData = $_POST[usr]. "n";
if ($fh)
    {
        $found = false;
        while (!feof($fh))
        {
            $buffer = fgets($fh);
            if (strpos($buffer, $stringData) == TRUE) {
                echo "This username is already whitelisted.";
                $found = true;
                break;
        }
        if (!$found) {
            fwrite($fh, $stringData);
            echo "Username ". $stringData. " is now whitelisted.";
        }
        fclose($fh);
    }

Answer by Starx

I don’t like you are already opening the file for writing without finding out whether a match occurs or not

$username = "thegreatone";
$lines = file("yourfile.txt");
foreach($line as $no => $line) {
    if(strstr($line,$username)) {
       //Now start the hand
       $fp = fopen('whitelist.txt', 'a+');
       fwrite($fp, 'rn'.$username);
       fclose($fp);

       //Since the search was true... no need to continue the loop
       break;    
    } 
}

Author: Nabin Nepal (Starx)

Hello, I am Nabin Nepal and you can call me Starx. This is my blog where write about my life and my involvements. I am a Software Developer, A Cyclist and a Realist. I hope you will find my blog interesting. Follow me on Google+

...

Please fill the form - I will response as fast as I can!