Skipping blank lines with strpos in PHP - php

I want to read a line and if it is blank, skip it. It seems to work but the text file I'm reading begins with three blank lines and it only skips one of them. How can I make it skip all three blank lines at the beginning of the file as well as all other blank lines throughout the file?
$handle = fopen("testlog.log", "r");
if ($handle) {
while (!feof($handle)) {
$buffer = fgets($handle, 4096);
$pos = strpos( $buffer, '/n' );
if ($pos == false) {
//do stuff
}
}
Edit
Here's the full code. I know I'm doing something wrong...
There are multiple delimiters in the log file, is there a way to condense the variables?
Log file: http://www.castleotwonline.com/crawlerlogs/testlog.log
<?php
$handle = fopen("testlog.log", "r");
$conn = mysql_connect("localhost","user","pass");
mysql_select_db("castleot_crawlerlogs",$conn);
if ($handle) {
while (!feof($handle))
{
$buffer = fgets($handle, 4096);
$buffer0 = fgets($handle, 4096);
$buffer1 = fgets($handle, 4096);
$buffer2 = fgets($handle, 4096);
$buffer3 = fgets($handle, 4096);
$buffer4 = fgets($handle, 4096);
$buffer5 = fgets($handle, 4096);
$pos = strpos( $buffer, '\n' );
if ($pos === false) {
list($version,$versiondata)=explode(" : ",$buffer0);
list($board,$boarddata)=explode(" --- ",$buffer1);
list($abilityfriend,$abfdata)=explode(" : ",$buffer2);
list($abilityenemy,$abedata)=explode(" : ",$buffer3);
list($mana,$manadata)=explode(" : ",$buffer4);
list($secret,$secretdata)=explode(": ",$buffer5);
$secret = "Enemy_secret";
$sql = "INSERT INTO logtest ($version,$board,$abilityfriend,$abilityenemy,$mana,$secret) VALUES('".$versiondata."','".$boarddata."','".$abfdata."','".$abedata."','".$manadata."','".$secretdata."')";
echo $version." : ".$versiondata."<br>".$board." : ".$boarddata."<br>".$abilityfriend." : ".$abfdata."<br>".$abilityenemy." : ".$abedata."<br>".$mana." : ".$manadata."<br>".$secret." : ".$secretdata."<br>";
mysql_query($sql,$conn) or die(mysql_error());
}
}
}
else {
echo "File load failed.";
}
fclose($handle);
?>

Try this:
$handle = fopen("testlog.log", "r");
if ($handle) {
while (!feof($handle)) {
$buffer = fgets($handle, 4096);
if (!empty($buffer) && $buffer[0] !== "\n") {
// do stuff
}
}
}

Related

How Merging multiple CSV files without headers being repeated (using PHP)?

I'm very rookie in PHP and when I combine several csv files with this code, several headers are shown. How could I leave a single header?
I am using a ubuntu 18.04 server with PHP 7.1
<?php
$csvdir = "./csv";
$csvcontent = '';
if (is_dir($csvdir)) {
if ($handle = opendir($csvdir)) {
while (($file = readdir($handle)) !== false) {
if (substr($file, -4) === ".csv") {
$csvcontent .= file_get_contents($csvdir . $file);
}
}
closedir($handle);
}
}
$result = fopen('./todos.csv', 'w');
fwrite($result, $csvcontent);
fclose($result);
?>
According to this answer with example code to skip first lines after getting file contents:
$content = file_get_contents($filename);
$lines = explode("\n", $content);
$skipped_content = implode("\n", array_slice($lines, 2));
You might alter your code like this (although, personally, i might simply alter the production of the csv files to stop producing headers...as exploding the content could slow down your processes).
<?php
$got_headers = 0;
$csvdir = "./csv";
$csvcontent = '';
if (is_dir($csvdir)) {
if ($handle = opendir($csvdir)) {
while (($file = readdir($handle)) !== false) {
if (substr($file, -4) === ".csv") {
if (empty($got_headers)) {
// get the headers the first time only
$csvcontent .= file_get_contents($csvdir . $file);
$got_headers = 1;
} else {
// now, pull the lines after the first
$content = file_get_contents($csvdir . $file);
$lines = explode("\n", $content);
$csvcontent .= implode("\n", array_slice($lines, 1));
}
}
}
closedir($handle);
}
}
$result = fopen('./todos.csv', 'w');
fwrite($result, $csvcontent);
fclose($result);
This has the added benefit of not requiring you to hold the entirety of the resulting file in memory:
$files = []; // use your existing code to build a list of files
$first = true;
$out = fopen('todos.csv', 'wb');
foreach( $files as $file ) {
$in = fopen($file, 'rb');
$line = fread($in); // get the header line
// write only the first file's header
if( $first ) {
fwrite($out, $line);
$first = false;
}
// transcribe the rest of the file.
while( $line = fread($in) ) {
fwrite($out, $line);
}
fclose($in);
}
fclose($out);

Grab particular data from row

I have the following peoplelist.txt text file with 2 rows:
1,Hello,hello#me.com,Boss
2,Hello Again,hello2#me.com,Boss
My code to output this is:
$handle = fopen("peoplelist.txt", "r");
if ($handle) {
while (($line = fgets($handle)) !== false) {
echo $line;
}
fclose($handle);
}
Is it possibly instead of outputting the entire line, I just output the data in the 2nd column (aka Hello & Hello Again)?
Since that's CSV data:
while (($line = fgetcsv($handle)) !== false) {
echo $line[1];
}
$handle = fopen("/temp/peoplelist.txt", "r");
if ($handle) {
while (($line = fgets($handle)) !== false) {
$parts = explode(',',$line);
echo $parts[1] . PHP_EOL;
}
fclose($handle);
}

How to skip fwrite() for x lines

I'm creating PHP program which should find in *.txt file line that starts with word "tak" and skip that program from rewriting it to the next *.txt file. So what I want to achieve now is prevent it from writing, for example, 2 more lines after line that started with "tak" word. Here is my CODE:
<?php
$file2 = fopen("out.txt", "w") or die("Unable to open file!");
$handle = fopen("plik.txt", "r");
if ($handle) {
while (($line = fgets($handle)) !== false) {
if (strpos($line, 'tak') === 0) {
echo 'found<br/>';
}
else {
fwrite($file2, $line);
}
}
fclose($handle);
echo 'OK';
}
else {
echo "can't read the file";
}
?>
I think using file, a for loop, and file_put_contents would work and be simpler.
$file2 = "out.txt";
//$file = file($file2) or die("Unable to open file!");
$file = array('asdf',
'asdf',
'asdf',
'tak',
'1',
'2',
'3',
'4');
file_put_contents($file2, ''); // truncate file;
for($i = 0; $i < count($file); $i++) {
$line = $file[$i];
if (strpos($line, 'tak') === 0) {
echo 'found<br/>';
$i = $i + 2;
} else {
// file_put_contents($file2, $line, FILE_APPEND | LOCK_EX);
echo $line;
}
echo 'ok';
}
Demo: https://eval.in/597694
Output (kinda messy but gets the point tak, 1, and 2 skipped):
asdfokasdfokasdfokfound<br/>ok3ok4ok
You can do it by keeping boolean and integer variable to count the number of occurrence. Like this,
<?php
$file2 = fopen("out.txt", "w") or die("Unable to open file!");
$handle = fopen("plik.txt", "r");
if ($handle) {
$stopWriteLines=false;
$max_line_skip=2;
// Taking above two variables for our logic.
while (($line = fgets($handle)) !== false) {
if($stopWriteLines) {
$max_line_skip--;
}
// Above condition check if we found tak in line then decrements the skip lines count.
if (strpos($line, 'tak') === 0) {
echo 'found<br/>';
$stopWriteLines=true; // Setting Boolean variable to skip writing lines.
}
else {
if(!$stopWriteLines) { // will write only if Boolean variable is set to true.
fwrite($file2, $line);
}
}
if($max_line_skip==0) {
$stopWriteLines=false;
}
// Above condition will make Boolean variable false after skipping 'n' lines.
}
fclose($handle);
echo 'OK';
}
else {
echo "can't read the file";
}
?>
Please check the explanations in code for better understanding of respected code sections.

Php fopen delete each readed line while reading

I have a code
$handle = fopen(getcwd() . "/emails.txt", "r");
if ($handle) {
while (($line = fgets($handle)) !== false) {
SendEmails($line,$strSubject,$strMessage,$txtFormName,$txtFormEmail,$fname,$ftype,$tmp_path);
$line.delete; // here i need to delete each readed line
}
fclose($handle);
} else {
echo "error opening the file.";
}
How to delete each readed line while reading?
Try This
$handle = fopen(getcwd() . "/emails.txt", "r");
$readedlines="";
if ($handle) {
while (($line = fgets($handle)) !== false) {
SendEmails($line,$strSubject,$strMessage,$txtFormName,$txtFormEmail,$fname,$ftype,$tmp_path);
$readedlines=$readedlines.$line;
fclose($handle);
$newFileContent=str_replace($readedlines,"",file_get_contents($filename));
$handle=fopen($filename, "w");
fwrite($handle,$newFileContent);
fclose($handle);
} else {
echo "error opening the file.";
}
I mean just concate all readed line into one string and replace through the whole string of file content.
Hope that helps
// Get file contents
$contents = file_get_contents('/emails.txt');
// Explode to get contents in an array
$rows = explode("\n", $contents);
file_put_contents('/emails.txt', "");
// Loop through all rows in emails.txt
foreach ($rows as $row) {
// If sending the email fails, add row to $notSent
if (false === SendEmails($row, $strSubject, $strMessage, $txtFormName, $txtFormEmail, $fname, $ftype,$tmp_path)) {
$contents = file_get_contents('/emails.txt');
$contents .= $row."\n";
file_put_contents('/emails.txt', $contents);
}
}

Remove Line From CSV File

I have .csv file with 4 columns. What's the easiest way to remove a line identical with the id of the first column? Here's where I got stuck:
if($_GET['id']) {
$id = $_GET['id'];
$file_handle = fopen("testimonials.csv", "rw");
while (!feof($file_handle) ) {
$line_of_text = fgetcsv($file_handle, 1024);
if ($id == $line_of_text[0]) {
// remove row
}
}
fclose($file_handle);
}
Unfortunately, databases were not a choice.
$table = fopen('table.csv','r');
$temp_table = fopen('table_temp.csv','w');
$id = 'something' // the name of the column you're looking for
while (($data = fgetcsv($table, 1000)) !== FALSE){
if(reset($data) == $id){ // this is if you need the first column in a row
continue;
}
fputcsv($temp_table,$data);
}
fclose($table);
fclose($temp_table);
rename('table_temp.csv','table.csv');
I recently did a similar thing in for a newsletter unsubscription, heres my code:
$signupsFile = 'newsletters/signups.csv';
$signupsTempFile = 'newsletters/signups_temp.csv';
$GLOBALS["signupsFile"] = $signupsFile;
$GLOBALS["signupsTempFile"] = $signupsTempFile;
function removeEmail($email){
$removed = false;
$fptemp = fopen($GLOBALS["signupsTempFile"], "a+");
if (($handle = fopen($GLOBALS["signupsFile"], "r")) !== FALSE) {
while (($data = fgetcsv($handle)) !== FALSE) {
if ($email != $data[0] ){
$list = array($data);
fputcsv($fptemp, $list);
$removed = true;
}
}
fclose($handle);
fclose($fptemp);
unlink($GLOBALS["signupsFile"]);
rename($GLOBALS["signupsTempFile"], $GLOBALS["signupsFile"]);
return $removed;
}
this uses the temp file method of writing out the csv line by line to avoid memory errors. Then once the new file has been created, it deletes the original and renames the temp file.
You can modify this code so that it looks for an ID instead of an email address eg:
$id = $_GET['id'];
$fptemp = fopen('testimonials-temp.csv', "a+");
if (($handle = fopen('testimonials.csv', "r")) !== FALSE) {
while (($id= fgetcsv($handle)) !== FALSE) {
if ($id != $data[0] ){
$list = array($data);
fputcsv($fptemp, $list);
}
}
fclose($handle);
fclose($fptemp);
unlink('testimonials.csv');
rename('testimonials-temp.csv','testimonials.csv');
$id = $_GET['id'];
if($id) {
$file_handle = fopen("testimonials.csv", "w+");
$myCsv = array();
while (!feof($file_handle) ) {
$line_of_text = fgetcsv($file_handle, 1024);
if ($id != $line_of_text[0]) {
fputcsv($file_handle, $line_of_text);
}
}
fclose($file_handle);
}
You can do:
$new = '';
while (!feof($file_handle))
{
$line_of_text = fgetcsv($file_handle, 1024);
if ($id != $line_of_text[0])
{
$new .= implode(',',$line_of_text) . PHP_EOL;
}
}
basically you running threw each line and check if the id does NOT match the id sent in the get parameter, if it does not then it writes the line to the new container / variable.
And then rewrite the $new value to the file, this should work ok:
How big is the file
Do you have a CSV Header on line 0?
I have found a solution, that does not need to copy the file.
$file = 'testimonials.csv'
// open two handles on the same file
$input = fopen($file ,'r'); // read mode
$output = fopen($file, 'c'); // write mode
if($input !== FALSE && $output !== FALSE) { // check for error
while (($data = fgetcsv($input, $CSVLIMIT, $sep)) !== FALSE) {
if(reset(data) == $id) {
continue;
}
fputcsv($output, $data, $sep);
}
// close read handle
fclose($input);
// shorten file to remove overhead created by this procedure
ftruncate($output, ftell($output));
fclose($output);
}
Note: only one of those fopen commands could fail, leaking the handle for the second one. It would be good, to check both handles independetly and close them on a error.

Categories