views:

106

answers:

5

Hi there,

Thank you for taking the time to read this and I will appreciate every single response no mater the quality of content. :)

I'm trying to create a php script which searches a text file for specific text. A person types in the specific text within a HTML form and the php script should search for that specific text within the text file.

The value of the input field of the HTML form is "username" and within the php document, the variable "$username" is the entered data, example shown below:

$username = $_POST['username'];

The text file below is called "begin.txt":

"AULLAH1" "01/07/2010 15:28 " "55621454" "123456" "123456.00"

"USERNAME" "7/3/2010 6:21 PM" "55621454" "123456" "123456.00"

"AULLAH1" "07/07/2010 15:05 " "55621454" "189450" "123456.00"

"SUPREMEGAMER" "7/8/2010 6:42 PM" "55621454" "123456" "123456.00"

If a person types into the HTML form "AULLAH1", I'd like the php script to grab the last "AULLAH1" entry in the text file (e.g. It should grab the third line and not the first, as the third line is the last entry to contain the text "AULLAH1"). Also with that, when a person types in a specific text, it shouldn't simply grab the document or the text, it should grab the whole line: "AULLAH1" "07/07/2010 15:05 " "55621454" "189450" "123456.00" and place it into a php variable, maybe something like "$grabbed"? If possible at all.

All assistance is appreciated and I look forward to your replies; thank you. :) If I didn't explain anything clearly and/or you'd like me to explain in more detail, please reply. :)

Thank you.

+2  A: 

You can use SplFileObject and iterate over the file line by line.

Please note that iterating over the file is much more memory efficient than using file() or file_get_contents() because it does not read the entire file content into an array or a variable.

$username = 'AULLAH1';
$file = new SplFileObject("data.csv");
$grabbed = FALSE;
while (!$file->eof()) {
     $data = $file->fgetcsv(' ');
     if($data[0] === $username) {
         $grabbed = $file->current();
     }
}
echo $grabbed;

Because fgetcsv() takes into account delimiters, enclosures and escape characters when parsing the line, it is not exactly fast though. If you have to parse a couple hundred or thousand lines this way, make sure you actually have the need for it.


An alternative would be to just check if the current line contains the username string somewhere. In the file format you show in the question, this would be feasible because the remaining fields contain digits, so there cannot be any false positives:

$username = 'AULLAH1';
$file = new SplFileObject("data.txt");
$grabbed = FALSE;
foreach($file as $line) {
    if(strpos($line, $username) !== FALSE) {
        $grabbed = $line;
    }
}
echo $grabbed;

If you want to make sure the $username was found at position 1, change the if condition to test for === 1.


If, for some reason, you want to have all lines where the username occurs, you can write a custom FilterIterator to iterate over the file contents, e.g.

class UsernameFilter extends FilterIterator
{
    protected $_username;
    public function __construct(Iterator $iterator, $username)
    {
        $this->_username = $username;
        parent::__construct($iterator);
    }
    public function accept()
    {
        return strpos($this->current(), $this->_username) !== FALSE;
    }
}

Then you can simply use foreach. The FilterIterator will pass each line to accept() and only those lines for which it returns TRUE are actually used.

$filteredLines = new UsernameFilter(new SplFileObject('data.txt'), 'AULLAH1');
foreach($filteredLines as $line) {
    echo $line;
}

The above would output

"AULLAH1" "01/07/2010 15:28 " "55621454" "123456" "123456.00"
"AULLAH1" "07/07/2010 15:05 " "55621454" "189450" "123456.00"

If you want these lines in an array, you can do

$lines = iterator_to_array($filteredLines);

and to look at the last item

echo end($lines);
Gordon
Hi Gordon, thank you for your response, I extremely appreciate it. The first code which you provided did the job for me and it works more than flawlessly. I simply can't thank you enough for your efforts. ;) Thank you.
AUllah1
@AUllah1 you're welcome.
Gordon
+3  A: 

i would not use a text file to store credentials but if you must atleast change the format of the text file to a CSV layout

have it like this

AULLAH1,01/07/2010 15:28,55621454,123456,123456.00
USERNAME,7/3/2010 6:21 PM,55621454,123456,123456.00
AULLAH1" "07/07/2010 15:05 " "55621454" "189450" "123456.00
SUPREMEGAMER,7/8/2010 6:42 PM,55621454,123456,123456.00

read the file line my line in PHP

<?php
$lines = file('begin.txt');
foreach($lines as $line)
{
     if(preg_match('/(?<username>.*?),(?<ts>.*?),(?<id_1>.*?),(?<id_2>.*?),(?<balance>.*?)/',$line,$parts))
     {
         if($_POST['username'] == $parts['username'])
         {
             //Do what you need here.
             break;
         }
     }
}
?>

you could also use explode witch is faster but is limited to auto generate keys forthe array!

<?php
$lines = file('begin.txt');
foreach($lines as $line)
{
    $parts = explode(',',$line);
     if($_POST['username'] == $parts[0])
     {
         //Do what you need here.
         break;
     }
}
?>
RobertPitt
You could also use the `fgetcsv()` function, which handles delimiters and escape characters for you and returns each line as an array.
Lèse majesté
Hi Robert, thank you for your response, I extremely appreciate it. Unfortunately I can't change the format of text document to csv, as at the moment, the text document has been specifically coded to dynamically enter data. Don't worry though, the data isn't nothing too important. ;) Again, I appreciate your response and all your efforts. ;)
AUllah1
the problem is that if you explode by spaces if theres a space within the quotes such as `"USER NAME" "1245345"` it would return 3 values `"USER`,`NAME"`,`"12345345"` like so, so witc is best to have some charactor that would not be used as often such as a pipe `|`... your best of using the preg_match function and match strings inside the quotes and delimiter by spaces OUTSIDE the quotes.
RobertPitt
The Regex doesnt work. `preg_match()` returns the number of times pattern matches. `$parts` will be an integer.
Gordon
whoops. updated..
RobertPitt
+2  A: 

Using preg_match_all() could be a solution:

$file = file_get_contents($filename);
$username = 'ALLUAH1';
preg_match_all('/^"'.preg_quote($username, '/').'".*$/m', $file, $matches);
  // Note that the '/m' flag of the regex makes '^' and '$' match
  // the beginning and end of each line.
  // Also note that I am using preg_quote() to escape special regex characters

$grabbed = array_pop($matches[0]);

Now $grabbed should hold the value of the last line of that user.

Related links:

Frxstrem
Hi Frxstrem, thank you for your response, I extremely appreciate it. Unfortunately, after I add the line "echo $grabbed", the data doesn't seem to appear. That most likely will be a problem on my end and not yours. Again, I appreciate the response and I am extremely grateful that you replied. ;) Thank you.
AUllah1
@Aullah1 @Frxstrem misspelled the `$username`. If you change it to read `AULLAH1` it works.
Gordon
+2  A: 

This is the absolute simplest way I can think of implementing this. This method simply runs through the lines of the file in reverse order, and so does not need to search each and every line. It also assumes the username, wrapped in double quotes, is the very first thing on each line of the input file.

$username = "AULLAH1";
$input_file = file("begin.txt");

$grabbed = "";

for($i = count($input_file) - 1; $i >= 0; $i--)
{
  // Note: Exactly zero (string starts the line), NOT "FALSE"
  if(strpos($input_file[$i], "\"$username\"") === 0)
  {
    $grabbed = $input_file[$i];
    break;
  }
}
sargant
Hi sargant, your coding is amazing and I like the way it reads the data. One thing though, it doesn't seem to display the data after the coding has been entered into a php document. Of course, that will most likely be a problem on my end and not yours. I extremely appreciate your response as well as the efforts you've put into this. Thank you. ;)
AUllah1
There is a syntax error in the code. You have to remove the second parenthesis before the `===` in the `if` block.
Gordon
Changed the parenthesis
sargant
+2  A: 

This is the shortest I can come up with:

$list = file_get_contents('data.txt');
echo strstr(substr($list, strrpos($list, 'AULLAH1')-1), PHP_EOL, TRUE);

This will read the file into memory. Then it finds the offset of the last occurence of the string 'AULLAH1'. Everything one letter before this occurence up to the next newline character will be returned.

This requires PHP5.3 due to the strstr()'s third argument and requires more memory than the iterator solution above. Depending on your newlines, you might have to change PHP_EOL to the newline chars used in the file.

Gordon
Hi Gordon, that definitely is some short coding and is very efficient. Although, I don't currently have a server running PHP5.3. None the less, I appreciate your efforts in any way. You've been an extreme help and I am grateful for your response. ;) Thank you.
AUllah1
@AUllah thanks. IMO, speedwise the above should be faster than any of the other variants that do read in the file completely. Fastest and most memory efficient should be `SplFileObject` with `strpos` though.
Gordon