The loop never stop, also it always print, not only when $i is equal 8
$file = file_get_contents ($fileUrl);
$i = 0;
while ($line = explode ("\r\n", $file)) {
if ($i == 8) {
print_r ($line);
exit ();
}
$i++;
}
By the way, I need to use file_get_contents because I am using DOM, but I use that code because I need the data in line number 8, is there any better way to get a specific line
It is infinite because explode always explodes the entire file string and it never fails. You can read it into an array, but this is only useful without the exit if you are doing things with other lines in the file:
foreach(file($fileUrl) as $line) {
if ($i == 8) { // actually the ninth line
print_r ($line);
}
$i++;
}
Or read it as you are and get the proper line:
$lines = explode("\r\n", $file);
print_r($lines[8]); // actually the ninth line
You're not looping through the lines. You're setting $line to an array of all the lines, not a specific line. And you're setting it to the same thing every time through the loop, so the while condition will never change.
However, the loop should stop when $i == 8 because of the exit() call. It will then print all the lines with print_r().
If you want line 8, just index the array.
$lines = explode("\r\n", $file);
if (count($lines) >= 9) {
print_r($lines[8]);
}
FYI, you can also use file() to read a file and split it into lines:
$lines = file($fileUrl, FILE_IGNORE_NEW_LINES);
if you want to get the 8th line, you can simply do this:
$line = explode ("\r\n", $file)[8];
print_r($line);
without using a loop
and regarding you question for infinite loop
$line = explode ("\r\n", $file)
returns a true, since you are just assigning an array to this variable.
you should use foreach here like this:
foreach(explode ("\r\n", $file) as $line){
// TO DO
}
Related
EDIT: checking for !empty works - but I would still like to know why the while seems to be continuing on after the end of the file. Thanks!
I am trying to parse a file that looks like:
export NTPSERVER_1 NTPSERVER_2 NTPSERVER_3 PSLOGHOST LOGHOST RSSHHOST RHPORT
NTPSERVER_1=8.8.8.8
NTPSERVER_2=
NTPSERVER_3=
LOGHOST="8.8.8.8"
PSLOGHOST=""
RSSHHOST="8.8.8.8"
RHPORT=88888
It's working great, except there is an extra last value in the array with no key and a null value. I have tried adding a check for $line being null to no avail. And I have double checked that the file does not have any blank lines after the RHPORT line.
I am getting a "Notice: Undefined offset: 1" message and last thing in the array is [""]=> NULL
I don't understand why the while doesn't seem to be stopping at the end of the file.
$file = fopen("files/network.conf","r");
$i = 0;
while(! feof($file)) {
$line = fgets($file);
if ($i > 0 && !is_null($line)) { // skipping first line of file
$array = explode('=',$line);
$fileValues[$array[0]] = $array[1];
}
$i++;
}
fclose($file);
I will recommend you to use file() function
$array = file('file path', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$final_array = [];//empty array declaration
foreach($array as $arr){ // iterate over array get from file() function
$exploded_array = explode('=',$arr);
$final_array[$exploded_array[0]] = $exploded_array[1];
}
print_r($final_array);
As you can see only one-line code needed and you will get desired array
You can use file_get_contents and regex to get the values.
// Uncomment line below
//$str =file_get_contents("files/network.conf");
$str = 'export NTPSERVER_1 NTPSERVER_2 NTPSERVER_3 PSLOGHOST LOGHOST RSSHHOST RHPORT
NTPSERVER_1=8.8.8.8
NTPSERVER_2=
NTPSERVER_3=
LOGHOST="8.8.8.8"
PSLOGHOST=""
RSSHHOST="8.8.8.8"
RHPORT=88888';
// Find lines with = and save them to $matches[1] and [2]
Preg_match_all("/(\w+)\=(.*)/", $str, $matches);
// Create array as you expect
Foreach($matches[1] as $key => $val){
$res[$val] = str_replace('"','',$matches[2][$key]); // remove " if it exists.
}
Var_dump($res);
https://3v4l.org/CO59t
I've tried a lot of potential solutions, but none of them are working for me.
The simplest one:
$file = file('list.html');
array_pop($file);
isn't doing anything at all. Am I doing something wrong here? Is it different because it's an html file?
This should works :
<?php
// load the data and delete the line from the array
$lines = file('filename.txt');
$last = sizeof($lines) - 1 ;
unset($lines[$last]);
// write the new data to the file
$fp = fopen('filename.txt', 'w');
fwrite($fp, implode('', $lines));
fclose($fp);
?>
I created a function to remove x number of lines from the bottom. Set $max to the number of lines you want to delete.
function trim_lines($path, $max) {
// Read the lines into an array
$lines = file($path);
// Setup counter for loop
$counter = 0;
while($counter < $max) {
// array_pop removes the last element from an array
array_pop($lines);
// Increment the counter
$counter++;
} // End loop
// Write the trimmed lines to the file
file_put_contents($path, implode('', $lines));
}
Call the function like this:
trim_lines("filename.txt", 1);
The variable $path can be a path to the file or a filename.
Remove first and last line of a variable in PHP:
Using phpsh interactive shell:
php> $test = "line one\nline two\nline three\nline four";
php> $test = substr($test, (strpos($test, "\n")+1));
php> $test = substr($test, 0, strrpos($test, "\n"));
php> print $test;
line two
line three
You might have meant "The last non blank line". In that case do this:
Notice that there are three blank lines after the content. This gets rid of those lines before removing the last:
php> $test = "line one\nline two\nline three\nline four\n\n\n";
php> $test = substr($test, 0, strrpos(trim($test), "\n"));
php> print $test;
line one
line two
line three
You are only reading the file, you now need to write the file
Look into file_put_contents etc
Suppose that I have 2 files:
File1.txt
10;30;15;40;12;14;15
23;32;10;50;12;54;60
File2.txt
2;4;5;6;7;8;9
3;6;7;8;9;0;7
I want to subtration between these 2 files. Ex 10 - 2........
PHP code:
$file1 = 'File1.txt';
$file2 = 'File2.txt';
if(file_exists($file1)){
$files = fopen($file1,'r');
while(!feof($files)){
$data = explode(";",fgets($files));
if($title ==""){
$title = $data[0];
}
if(!empty($data[3])){
$cate = $data[3];
$filepmta = fopen($file2,'r');
while(!feof($filepmta)){
$hourData = explode(";",fgets($filepmta));
if(!empty($hourData[3])){
if($title ==""){
$title = $hourData[0];
}
if(!empty($btnHour)){
echo $percentRed = ((int)$data[2] - (int)$hourData[2]);
//it loads page so long time so I don know what's error.
}
}
}
It loads the page is so long time.I don know how to fix this,Anyone know help me please,thanks.
I would recommend just simply opening both files and storing the contents of the file into memory. IE Create 2 simple loops (not nested) which iterates through both files respectively and saves the content to an array.
Then make one more loop after the first two. Iterate through the third loop based on the array size of the first two. (I'm assuming you can assume they are both the same size, but it will be a good idea to add checks to make sure loop 1 and loop 2 produce the same size/length arrays.
Within the 3rd loop iterate through both previously two generated arrays with the same index.
Pseudo Code // even tho I said I'd do pseudo code, I ended up doing it all. :-/
$file_values1 = $file_values2 = $answers = array();
while(!feof($file1)) $file_values1[] = explode(';', fgets($file)); // loop 1
while(!feof($file2)) $file_values2[] = explode(';', fgets($file)); // loop 2
foreach($file_values1 as $key1 => $sub_array) { // loop 3
foreach($sub_array as $key2 => $value) // loop 4; hehe, oh wellz
{
$answers[] = $file_values1[$key1][$key2] = $file_values2[$key1][$key2]
}
}
Basically, the nested loop 4, meh. There ARE faster answers. The 3rd loop can be improved upon, it's O(N^2). I'll leave that for you to optimize. No free lunches. :-)
fgets() doesn't move the file pointer after the last line, so you're staying on the last line, feof() still returns false and you're trapped in an infinite loop.
The common way of doing what you want is:
while (($line = fgets($handle)) !== false) {
echo $line;
}
Have a look at the code example in fgets() documentation, it's quite exhaustive.
You're making this way more complicated than it has to be.
Open your files and read them both in with file(), which will give you an array of lines in each file.
Iterate over both line arrays simultaneously with a MultipleIterator.
Convert each lines' contents to arrays with str_getcsv() and an array_map() trick.
Iterate over each line values with another MultipleIterator.
Compute the subtraction and print it.
That's all it takes! I've implemented the above algorithm below.
$file1 = 'File1.txt';
$file2 = 'File2.txt';
$file1 = file( $file1);
$file2 = file( $file2);
$iter = new MultipleIterator;
$iter->attachIterator( new ArrayIterator( $file1));
$iter->attachIterator( new ArrayIterator( $file2));
foreach( $iter as $element) {
list( $line1, $line2) = array_map( 'str_getcsv', $element, array( ';', ';'));
$val_iter = new MultipleIterator;
$val_iter->attachIterator( new ArrayIterator( $line1));
$val_iter->attachIterator( new ArrayIterator( $line2));
foreach( $val_iter as $value) {
list( $el1, $el2) = $value;
echo ($el1 - $el2); echo ";";
}
echo "\n";
}
You can see from this demo, which statically defines the files as arrays, that this produces:
8;26;10;34;5;6;6;
20;26;3;42;3;54;53;
I need a script to count the number of pipe delmited entries in a text file that are all on one line. I found a script that counts lines and modified it thinking I might get it to work but sadly it still counts the lines, so at present putputs the value 1. Please can you have a look and help me with a solution? The text file looks something like this:
Fred|Keith|Steve|James
The script I was trying is this:
$file1 = "names.txt";
$line = file($file1);
$count = count(explode("|", $line));
echo "$file1 contains $count words";
Any assistance much appreciated.
Many thanks.
The fastest way is just to count the pipes and add one. Trim the string to make sure pipes at the beginning and end aren't counted as an item.
<?php
$contents = file_get_contents('names.txt');
$count = substr_count(trim($contents, "|\n "), '|') + 1;
echo "$file1 contains $count words";
There are multiple approaches to something like this, different ways to open the file, and different ways to interpret the data.
However, you're going to be looking for something similar to this:
<?php
$data = file_get_contents("names.txt");
$count = count(preg_split("/|/", $data));
echo "The file contains $count words.";
?>
Lots of ways to do this, here's my take...
// get lines as array from file
$lines = file('names.txt');
// get a count for the number of words on each line (PHP > 5.3)
$counts = array_map(function($line) { return count(explode('|', $line)); }, $lines);
// OR (PHP < 5.3) get a count for the number of words on each line (PHP < 5.3)
//$counts = array_map(create_function('$line', 'return count(explode("|", $line));'), $lines);
// get the sum of all counts
$count = array_sum($counts);
// putting it all together as a one liner (PHP > 5.3)...
$count = array_sum(array_map(function($line) { return count(explode('|', $line)); }, file('names.txt')));
// or (PHP < 5.3)...
// $count = array_sum(array_map(create_function('$line', 'return count(explode("|", $line));'), file('names.txt')));
You almost did it, there is only a small misunderstanding on how file works:
You have not a single but all lines in you line variable and you can access a single line with a numerical index starting at 0
$nunWords = count( explode ('|', $line[0] ) );
So to count the words on, let's say line 10 you would simply change the index to 9 ( because we start at 0 )
Another example
$lines = file ('yourfile');
foreach ( $lines as $curLine => $line )
{
echo "On line " . $curLine+1 . " we got " . count( explode ('|', $line ) ) . " words<br/>\n";
}
I have a txt file like so:
This is line 1.
This is line 2.
This is line 3.
This is the rest.
Lorem and so on.
I want to use PHP to get the first three lines into a $variable, and then get everything else in the document into a $variable.
I've had some degree of success with this:
<?php
$file = fopen("text.txt","r");
$count = "0";
while(! feof($file))
{
$count++;
if ($count=="1") {
$line1 = fgets($file);
}
if ($count=="2") {
$line2 = fgets($file);
}
if ($count=="3") {
$line3 = fgets($file);
}
//everything else?
}
echo $line1;
echo $line2;
echo $line3;
//echo $everythingelse;
fclose($file);
?>
The following works:
echo fgets($file);
But this doesn't:
$line1 = fgets($file);
So, A) what am I doing wrong with that, and B) how do I get the rest of the file, and C) is there a better way to implement this? I feel like my way is clumsy and someone'll suggest something obvious which can do all this.
Thanks guys!
This is easiest with file() which reads an entire file into an array of lines. You can then use array operations like array_splice() to remove the first three and return them, then join them back into strings with \n.
// Reads the file into an array
$lines = file($file);
// Cuts off everything after the first three
$the_rest = array_splice($lines, 3);
// leaving the first three in the original array $lines
$first_three = $lines;
// Stick them back together as strings by implode() with newlines
$first_three = implode("\n", $first_three);
$the_rest = implode("\n", $the_rest);
You could do this:
$data = file("text.txt");
$beginning = implode(PHP_EOL,array_splice($data,0,3));
$end = implode(PHP_EOL,$data);
Used functions: file, implode, array_splice and PHP_EOL constant.
A) Your code is fine until the end of the if: you can't simply assign the value returned from fgets to a variable within a while, because the loop will overwrite it next time, with the content of the next line and so on, until it have reached the last line, which is somehow always empty. When you directly print the output of fgets, the while will echo one line by one as it proceeds in the loop.
B) You code just runs fine with this small correction: use the concatenating assignment operator to append the line to the variable instead of overwriting it. (String Operators)
<?php
$file = fopen("text.txt","r");
$count = "0";
while(!feof($file)) {
$count++;
switch ($count) {
case "1":
$line1 = fgets($file);
break;
case "2":
$line2 = fgets($file);
break;
case "3":
$line3 = fgets($file);
break;
default:
$everythingelse .= fgets($file);
}
}
echo $everythingelse;
fclose($file);
echo "\n\n\n\n\n\n";
echo "Plus, here is line one: ".$line1."\n";
echo "This is line three: ".$line3."\n";
echo "And finally, line two: ".$line2."\n";
(I also replaced your if with a switch, which does the same)
An example output:
C) I think that your method fixed it's fine for your purpose, specially if you already getting the file contents through fgets (and thus using a while). This method is native to work inside a while like yours. Of course you can also do as suggested by Kolink and Michael, using implode, which may even be faster.