I'm working on a script that edits PHP files contents. So far, i'm able to check if the line is empty on the file and then write what I need into it. However I need to find a way to loop through the array until it finds the next empty line if the first query was not empty.
For example, I want to edit this PHP file - example.php - which contains the following:
<?php
I am not an empty line.
I am not an empty line.
I am not an empty line.
?>
My script:
// File variables
$file = 'path/example.php';
$content = '';
// Check if the file exists and is readable
if (file_exists($file) && is_readable($file)) {
$content = file_get_contents($file);
}
// put lines into an array
$lines = explode("\n", $content);
//Get the fourth line
$Getline = $lines[3];
// check if the line is emptpy
if (empty($Getline) && $Getline !== '0') {
// Write something in the file
}
else {
// Find the next empty line
}
So all I need is to loop through the array until it finds the next empty line. Although I'm not sure how do that.
Use PHP file() function instead of file_get_contents() function. It will read the file in array format itself.
Then you can parse this array using foreach() and can check blank value in it.
May this will help you.
<?php
foreach($lines as $line)
{
// check if the line is empty
if (empty($line) || $line == '')
{
//Line = empty and do stuff here.
}
}
?>
Related
I am working on simple debug script that would allow me (when save button is pushed) to add new lines to .txt file and then on page load, get whatever was saved last time.
so for example i have my user_input.txt file and when i press save - i am adding timestamp and textarea contents to this file. When page is loaded again, i am getting contents from last save.
For the moment i have this code for get:
$current_user_input = file_get_contents('user_input.txt');
if($current_user_input === false) {
$current_user_input = '';
}
and for to set:
if($_POST) {
if($_POST['user_input']) {
$file = 'user_input.txt';
file_put_contents($file, $_POST['user_input']);
}
}
Obviously for the moment its just overwriting the text file and getting all its content, how do i modify it so it does what i described above?
For the save, you need to append the data (as AjAX's comment says using FILE_APPEND), but also adding an end of line to ensure that they appear on separate lines.
if($_POST) {
if($_POST['user_input']) {
$file = 'user_input.txt';
file_put_contents($file, $_POST['user_input'].PHP_EOL, FILE_APPEND);
}
}
You can then retrieve the last line using file() which reads the file in line by line into an array and take the last element...
$oldInput = file($file);
if(!empty($oldInput)) {
$current_user_input = array_pop($oldInput);
}
else {
$current_user_input = '';
}
Update:
For multi-line content you could change the new lines to <br /> tags...
file_put_contents($file,
str_replace( PHP_EOL, '<br />', $_POST['user_input']).PHP_EOL,
FILE_APPEND);
Which would keep all content on a single line.
I have a file users.txt which contains:
"ID" "Access" ;Expire>>26-08-2013<<
"ID" "Access" ;Expire>>27-08-2013<<
"ID" "Access" ;Expire>>28-08-2013<<
I wan't to check if the Expire date is greater than current datetime, and if so I want to add a semicolon at the begin of that line or simply delete that line.
The code i wrote so far for that is following:
$files = file('users.txt');
foreach ($files as $line) {
$pattern = '/>>(.*)<</';
preg_match($pattern, $line, $matches);
$expiredate = strtotime($matches[1]);
$currdate = strtotime(date('d-m-Y'));
if ($currdate > $expiredate) {
echo 'access expired... edit/delete the line<br/>';
} else {
echo 'do nothing, its ok -> switching to the next line...<br/>';
}
}
It retrieves the 'expire date' from every single line from file. It also checks if it's greater than current date but at this point i don't know how to edit (by adding semicolon at the begin) or delete the line which satisfy the condition.
Any suggestions?
Try like this one:
$files = file('users.txt');
$new_file = array();
foreach ($files as $line) {
$pattern = '/>>(.*)<</';
preg_match($pattern, $line, $matches);
$expiredate = strtotime($matches[1]);
$currdate = strtotime(date('d-m-Y'));
if ($currdate > $expiredate) {
// For edit
$line = preg_replace('/condition/', 'replace', $line); // Edit line with replace
$new_file[] = $line; // Push edited line
//If you delete the line, do not push array and do nothing
} else {
$new_file[] = $line; // push line new array
}
}
file_put_contents('users.txt', $new_file);
If you want to edit that line, use preg_match and push edited line to new array.
If you want to delete that line, do nothing. Just ignore.
If you want switching to the next line, push currently line to new array.
At final save new array to file.
The basic process is:
open main file in readonly mode
open secondary (temp) file in writeonly mode
Loop: readline from main file
process the line
save to secondary file
until end of file
close both files
delete the main file
rename the secondary file.
I have this script that I did, it basically grabs all the files in my "logs" folder and merge them all in one array file, my only problem is that, sometimes the script breaks if there is blank line or empty line! how can I tell it to automatically skip blank empty lines and go to next? blank lines are not necessarily at the top or bottom! could be in the middle of the csv file
<?php
$csv = array();
$files = glob('../logs/*.*');
$out = fopen("newfile.txt", "w");
foreach($files as $file){
$in = fopen($file, "r");
while (($result = fgetcsv($in)) !== false)
{
$csv[] = $result;
}
fclose($in);
fclose($out);
}
print json_encode(array('aaData' => $csv ));
?>
As you can read in the documentation for fgetcsv():
A blank line in a CSV file will be returned as an array comprising a single null field, and will not be treated as an error.
Checking for that before adding it to your data array should be sufficient:
while (($result = fgetcsv($in)) !== false) {
if (array(null) !== $result) { // ignore blank lines
$csv[] = $result;
}
}
This works 100% tested, simplest way. The explanation is that blank lines make fgetcsv return a non-empty array with just a null element inside.
if ($result[0] == NULL)
continue;
In short
$csv = array_map('str_getcsv', file($file_path, FILE_SKIP_EMPTY_LINES|FILE_IGNORE_NEW_LINES));
Explanation
file reads the content of the file into an array. The FILE_SKIP_EMPTY_LINES will skip the empty lines in the file.
array_map will apply the function str_getcsv on each element of the array. str_getcsv will parse the string input for fields in
csv format and return an array containing the fields.
Read more about str_getcsv
Read more about file
Read more about array_map
I want to do the following
I want to create .php file (executed via cronjobs) that will paste this code $files[] = 'example.php';
to other php file (paste.php) but it has to find the lastest $files[] line like regex $files[] = '(AnythingHere)'; and after this line to paste the new line. It can have random number of pages so I have no way of knowing.
<?php
if (!isset($php_file)) {
$files[] = 'page1.php';
$files[] = 'page2.php';
$files[] = 'page3.php';
$files[] = 'page4.php';
$file = $files[ rand(0,count($files)) ];
I hope you guys understand what I want; can anyone help me out with this one?
if you have ONLY $file[] = '...' in paste.php, you can simply append to the file:
$line = '$file[] = "pageX.php";' . PHP_EOL;
file_put_contents('paste.php', $line, FILE_APPEND);
of you want the last "page[]" enty.
$yourNewLine = '$file[] = "pageX.php";'; // this is an example. put your "line" prm here
$filename = 'paste.php';
$lines = file($filename);
$lines = array_reverse($lines)
$found = false;
$i = 0;
while ( ! $found )
{
if ( strpos($lines[$i], '$files[] = ' === 0) )
{
$found = true;
array_splice($lines, $i, 0, $yourNewLine.PHP_EOL);
}
$i++;
}
$lines = array_reverse($lines);
file_put_contents($filename, $lines);
Instead of doing it this way, how about instead setting your files array in a script and then include it at the top. This way you can reference the array directly and still only have to edit the file listing in only one place.
Quick and dirty first-fit solution:
Open the file
Read each line until you find one matching your regex for $files[] = ...
Read more lines until you find one that doesn't match the regex
Write each line read in 2 and 3 to the output file
Insert your new line into the output
Write the rest of the input to the output
This may not be the best way to approach the problem, drawbacks being that you have to read each line in and compare it with your regex until you find your insertion point. You'll also probably have a temporary file for output which you'll then rename to the original filename.
You'll have 2 while loops:
while (line does not match): read next line
and then
while (line does match): read next line
Someone who knows PHP better than I do might be able to come up with something a bit cleaner, but if you're just looking for something quick to get the job done, this ought to work.
Having this code:
$filesArray = array('page1.php','page2.php','page3.php','page4.php','page5.php',);
then getting the php file with $data = file("path/to/editable_file.php");
foreach($data as $line)
{
if(preg_replace("/\$filesArray\s=\sarray\([\w'.,]+()\);/", "'".$newfilename."',", $line, $match))
{
file_put_contents(implode("\r\n", $data));
break;
}
}
I have a txt file that has a change-log.I'm trying to display the new changes only for the current version.
I wrote a function to read the file and check every line if it has the wanted words, if it finds those words it starts to get the content and push it to an array.
I searched to see if there is an example but everyone was talking about how to stop at a specified line, not to start from one.
Here is the code I use:
public function load($theFile, $beginPosition, $doubleCheck) {
// Open file (read-only)
$file = fopen($_SERVER['DOCUMENT_ROOT'] . '/home/' . $theFile, 'r');
// Exit the function if the the file can't be opened
if (!$file) {
return;
}
$changes = Array();
// While not at the End Of File
while (!feof($file)) {
// Read current line only
$line = fgets($file);
// This will check if the current line has the word we look for to start loading
$findBeginning = strpos($line, $beginPosition);
// Double check for the beginning
$beginningCheck = strpos($line, $doubleCheck);
// Once you find the beginning
if ($findBeginning !== false && $beginningCheck !== false) {
// Start storing the data to an array
while (!feof($file)) {
$line = fgets($file);
// Remove space and the first 2 charecters ('-' + one space)
$line = trim(substr($line, 2));
if (!empty($line)) { // Don't add empty lines
array_push($changes, $line);
}
}
}
}
// Close the file to save resourses
fclose($file);
return $changes;
}
It's working currently, but as you can see it's nested loops and that's not good and in case the txt file grows it will take more time!
I'm trying to improve the performance, so does is there any better way to do this ?
much simpler than you think
$found = false;
$changes = array();
foreach(file($fileName) as $line)
if($found)
$changes[] = $line;
else
$found = strpos($line, $whatever) !== false;
That nested loop will not degrade performance, cause it's not really a nested loop in the sense that it is a combinatorially-growing loop over multiple variables. It isn't necessary to write it like that though. Here's another way that avoids it. Try this (pseudocode here):
// skim through the beginning of the file, break upon finding the start
// of the portion I care about.
while (!feof($file)) {
if $line matches beginning marker, break;
}
// now read and process until the endmarker (or eof...)
while (!feof($file)) {
if $line matches endmarker, break;
filter/process/store line here.
}
Also, doublechecking is absolutely not necessary. Why is that there?