I have a program that searches a text file to see if a certain string is in that file, which I have gotten to work fine. What I need to know is how to print a particular line of that text file. For example, if the file lists three street names each on its own line, and the program searches for one of them, I would want it to print out only the line that has that street name on it.
If the file looked like this: and the word being searched for was Rose Road,
I want it to only print out 6784 Rose Road
4543 Drock Drive
1254 HeadHill Road
6784 Rose Road
This is what I have so far, which checks if it's in the file, but I am just unsure how to print out a particular line.
$roadName = "Rose";
$handle = fopen("streets.txt", "r");
if(strpos(file_get_contents("streets.txt"),$roadName) !== false) //Checks to make sure its in the file.
{
echo fgets($handle); //This is what I was trying, but it only prints the 1st line.
}
file_get_contents and strpos have no effect on the file handle, so fgets just read from the beginning of the file.
You can read each line with fgets, test if it matches the string, and then print it.
while ($line = fgets($handler)) {
if (strpos($line, $roadName) !== false) {
echo $line;
break;
}
}
If the file is very large, this is better than the solution that uses file_get_contents, because it doesn't have to read the entire file into memory and then create a huge array of all the lines.
I would explode the lines into an array and the check every line:
$roadName = "Rose";
$file=file_get_contents("streets.txt")
if(strpos($file,$roadName) !== false) //Checks to make sure its in the file.
{
$lines = explode(PHP_EOL,$file);
foreach($lines as $line) {
if (strpos($line,$roadName) !== false) echo($line);
}
Related
Hellooo,
I wrote myself a little PHP experiment. This script counts how many times the user clicked a button labeled with a specific class (id="link_1", class="heart")
During each click, the script reads a txt file, finds the right id, then adds +1 to that id's number, like so:
#counte_me.php
$file = 'count_me.txt'; // stores the numbers for each id
$fh = fopen($file, 'r+');
$id = $_REQUEST['id']; // posted from page
$lines = '';
while(!feof($fh)){
$line = explode('||', fgets($fh));
$item = trim($line[0]);
$num = trim($line[1]);
if(!empty($item)){
if($item == $id){
$num++; // increment count by 1
echo $num;
}
$lines .= "$item||$num\r\n";
}
}
fclose($fh);
file_put_contents($file, $lines, LOCK_EX);
The result
# count_me.txt
hello_darling||12
This works wonderfully well. The problem happens when, from time to time, I find myself staring at an empty count_me.txt!
Not really know when or how it happens, but it does. I start making increments and happens, sometimes sooner, sometimes way later. It may be on my way to 10 or to 200 or to 320 or anything in between. Its totally random.
Driving me crazy. I'm not experienced enough, but that's why I'm playing with this thing.
Someone knows what I am doing wrong here for the file to get dumped like that?
UPDATE 1
So far, Oluwafemi Sule's suggestion is working, but I have to remove LOCK_EX from the file_put_contents for it to work, otherwise it just doesn't.
// NEW LINE ADDED
if (!empty($lines)) {
file_put_contents($file, $lines);
}
$lines is initially set to an empty string and only updated on the following condition.
if(!empty($item)) {
# and so on and so on
}
And finally at the end,
file_put_contents($file, $lines, LOCK_EX);
The reason that $lines still remains set to the initial empty string happens when item is empty. Remember the newline added from "$item||$num\r\n", there could be more than a single line added there(I won't put it past a text editor to add a new line to end that file .)
I suggest to only write to the file when $lines isn't empty.
if (!empty($lines)) {
file_put_contents($file, $lines, LOCK_EX);
}
My text file sample.txt. I want to exclude the first row from the text file and store the other rows into mysql database.
ID Name EMail
1 Siva xyz#gmail.com
2 vinoth xxx#gmail.com
3 ashwin yyy#gmail.com
Now I want to read this data from the text file except the first row(ID,name,email) and store into the MYsql db.Because already I have created a filed in database with the same name.
I have tried
$handle = #fopen($filename, "r"); //read line one by one
while (!feof($handle)) // Loop till end of file.
{
$buffer = fgets($handle, 4096); // Read a line.
}
print_r($buffer); // It shows all the text.
Please let me know how to do this?
Thanks.
Regards,
Siva R
It's easier if you use file() since it will get all rows in an array instead:
// Get all rows in an array (and tell file not to include the trailing new lines
$rows = file($filename, FILE_IGNORE_NEW_LINES);
// Remove the first element (first row) from the array
array_shift($rows);
// Now do what you want with the rest
foreach ($rows as $lineNumber => $row) {
// do something cool with the row data
}
If you want to get it all as a string again, without the first row, just implode it with a new line as glue:
// The rows still contain the line break, since we only trimmed the copy
$content = implode("\n", $rows);
Note: As #Don'tPanic pointed out in his comment, using file() is simple and easy but not advisable if the original file is large, since it will read the whole thing into memory as an array (and arrays take more memory than strings). He also correctly recommended the FILE_IGNORE_NEW_LINES-flag, just so you know :-)
You can just call fgets once before your while loop to get the header row out of the way.
$firstline = fgets($handle, 4096);
while (!feof($handle)) // Loop till end of file.
{ ...
I am reading the file and getting the particular line if there is a match for the searched string. There are bunch of strings to be searched which are stored in a array. I cant be opening the file every time when i loop through the array to get the string. But want to go to the first line of the file and start searching again. The file contains around 15k lines. If i open the file every time(inside the loop) its working fine. but if the open the file outside the loop. Only the first matched string line is returned.
$scheme_code =
array("106212","112422","114239","104685","100122","118191","131666");
foreach($scheme_code as $searchthis) {
$handle = #fopen("myfile", "r");
//DONT WANT TO DO THE ABOVE LINE FOR EVERY ITERATION
if ($handle)
{
//echo "handle open"."<br>";
while (!feof($handle))
{
$buffer = fgets($handle,4096);
if(strpos($buffer, $searchthis) !== FALSE){
$matches[] = $buffer;
}
}
}
}
But want to do something like this
$handle = #fopen("Myfile", "r");
foreach(){
// inside foreach
//go to the first line of the file
}
fclose($handle);
EDIT - I tried rewind(). I got the notice "rewind(): stream does not support seeking"
Here you can use file() function which will give you complete array of lines and after that you can match line by line without using your IO resource everytime by fopen.
<?php
$linesArray = file("/path/to/your/file.txt");
foreach($linesArray as $line){
// do the stuff or matching you want to perform line by line on $line
}
I'm trying my best to learn PHP and hack things out myself. But this part has me stuck.
I have two CSV files with hundreds of rows each.
CSV 1 looks like this:
name, email, interest
CSV 2 looks like this:
email only
I'm trying to write a script to compare the two files looking for duplicates. I only want to keep the duplicates. But as you can see, CSV 2 only contains an email. If an email in CSV 1 DOES NOT EXIST in CSV 2, then the row containing that email in CSV 1 should be deleted.
The end result can either overwrite CSV 1 or create a fresh new file called "final.csv"... whatever is easiest.
I would be grateful for the help.
I tried something along these lines with no luck:
egrep -v $(cat csv2.csv | tr '\n' '|' | sed 's/.$//') csv1.csv
and
grep -v -f csv22.csv csv1.csv >output-file
cheers,
marc
Here is a script that will loop through both files and output a 3rd file where email addresses in file2 are found in file1.
if (($file3 = fopen("file3.csv", "w")) !== FALSE) {
if (($file1 = fopen("file1.csv", "r")) !== FALSE) {
while (($file1Row = fgetcsv($file1)) !== FALSE) {
if (($file2 = fopen("file2.csv", "r")) !== FALSE) {
while (($file2Row = fgetcsv($file2)) !== FALSE) {
if ( strtolower(trim($file2Row[0])) == strtolower(trim($file1Row[1])) )
fputcsv($file3, $file1Row);
}
fclose($file2);
}
}
fclose($file1);
}
fclose($file3);
}
Couple of notes:
You may need to provide some additional arguments to fgetcsv, depending on how your csv is structured (e.g. delimiter, quotes)
Based on how you listed the contents of each file, this code reads the 2nd column of file1, and the 1st column of file2. If that's not really how they are positioned, you will need to change the number in the bracket for $file1Row[1] and $file2Row[0]. Column # starts at 0.
Script is current set to overwrite if file3.csv exists. If you want it to append instead of overwrite, change the 2nd argument of the $file3 fopen to "a" instead of "w"
Example:
file1.csv:
john,john#foobar.com,blah
mary,mary#blah.com,something
jane,jan#something.com,blarg
bob,bob#test.com,asdfsfd
file2.csv
mary#blah.com
bob#test.com
file3.csv (generated)
mary,mary#blah.com,something
bob,bob#test.com,asdfsfd
Solved! The problem was with Mac line breaks. Look at the code below to see the additions at the beginning and end of the code to fix that problem. Thank you Crayon Violent for all of your help!
ini_set('auto_detect_line_endings',TRUE);
if (($file3 = fopen("output.csv", "w")) !== FALSE) {
if (($file1 = fopen("dirty.csv", "r")) !== FALSE) {
while (($file1Row = fgetcsv($file1)) !== FALSE) {
if (($file2 = fopen("clean.csv", "r")) !== FALSE) {
while (($file2Row = fgetcsv($file2)) !== FALSE) {
if ( strtolower(trim($file2Row[0])) == strtolower(trim($file1Row[1])) )
fputcsv($file3, $file1Row);
}
fclose($file2);
}
}
fclose($file1);
}
fclose($file3);
}
ini_set('auto_detect_line_endings',FALSE);
I am attempting to insert the data from an uploaded file into a single dimension array.
The file is as such that there is one student number to a line like so:
392232,392231,etc
this is the most common way I've found online:
while (($line = fgetcsv($file, 25, ',')) !== FALSE) {
//$line is an array of the csv elements
print_r($line);
}
However form what I understand this will create an array ($line) for each row. Which is not what I want.
that aside I tried this to see if it is working and my code is not printing out the array after using ftgetcsv(). The file is successfully uploading.
here is my code:
if(isset($_FILES['csv_file']) && is_uploaded_file($_FILES['csv_file']['tmp_name'])){
//create file name
$file_path = "csv_files/" . $_FILES['csv_file']['name'];
//move uploaded file to upload dir
if (!move_uploaded_file($_FILES['csv_file']['tmp_name'], $file_path)) {
//error moving upload file
echo "Error moving uploaded file";
}
print_r($_FILES['csv_file']);
$file = fopen('$file_path', 'r');
while (($line = fgetcsv($file, 25, ',')) !== FALSE) {
//$line is an array of the csv elements
print_r($line);
}
//delete csv file
unlink($file_path);
}
First off, can anyone obviously see why it wouldnt work to at least print them as seperate arrays of data (each row).
Second, is it possible to set it so that it creates a 1d array of all rows in the file?
Many thanks,
Question 1 is because of
print_r($_FILES['csv_file']);
$file = fopen('$file_path', 'r');
should be:
$file = fopen($file_path, 'r');
and for Question 2, check out the array_push
1st Question:
This line will actually try to open a file called '$file_path' because you're using single quotes (so it doesn't expand to the value of the variable). You can just remove the quotes.
$file = fopen('$file_path', 'r');
$file is null after this.
2nd Question:
If all you want to do is convert a file into an array by lines you can use one of these instead:
file() - get whole file into a 1D array of lines of the file (closest to what you want)
fgets() - get a string per line per call; keep calling this until it returns false to get each line one at a time
file_get_contents() - get the whole file into a string and process as you like
According to PHP.net $line has to return as array.
"returns an array containing the fields read."
But if you are sure it's contains only one student number you can use $line[0] to get the first line value (Ignoring the ",")
Here are some general comments on your code:
You are passing the file path into the fopen() function incorrectly. The variable should not be surrounded with single quotes.
Since you are deleting the CSV file after processing it, moving it is unnecessary. Simply use $_FILES['csv_file']['tmp_name'] as the path to the file.
Since there is only one entry per row in your CSV file, simply access the first element of the array that is returned from fgetcsv(): $numbers[] = $line[0];