Extra blank value when parsing file to array - php

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

Related

what is wrong with this code, I am using PHP 8

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
}

How can I clean up this PHP code (If equals empty try next value)

Basically I have IF loop if a result equals empty and try the next key (line from text file)
English not my first language so please do not flag me
key.txt contains
randomkeyline
randomkeyline
randomkeyline
Now for the below code it goes 30 lines, how can i make it just try the next line try the next key (line? instead of having 300 lines of code
$key = file("keys.txt");//file in to an array
+1
$mykey = $key[1];
echo $mykey;
if($q){
$xml = file_get_contents("https://www.exampleurl.com/?q&key=$key(try next line if empty)");
}
echo $xml;
Put the keys in an array, and loop until you get a successful reply.
$keys = file("key.txt", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
foreach ($keys as $key) {
$xml = file_get_contents("https://exampleurl.com/?s=35&key=$key");
if ($xml) {
break;
}
}

How can I check if a username already exists in a file and also add his points to him?

I intentionally want to use a text file to do this. So I read a text file and I want to check if a username already exists in that text file or not and I want to either add this username to the text file if he doesn't exists or just add the points to him.
My current code:
<?php
$myfile = fopen("test.txt", "r") or die("Unable to open file!");
$file = fread($myfile,filesize("test.txt"));
//echo $file;
fclose($myfile);
//$username = $_REQUEST['username'];
//$points = $_REQUEST['point'];
$username = 'chinmay'; //chinmay is a username this is unique
$points = 200; //if username chinmay not exitst then Insert first time otherwise if username chimay exist then next onwards this point will update everytime in the text file.
$myfileWrite = fopen("test.txt", "a") or die("Unable to open file!");
$txt = $username."|".$points."\n";
fwrite($myfileWrite, $txt);
fclose($myfileWrite);
?>
test.txt:
chinmay|800
john|200
sanjib|480
debasish|541
This is my complete code. My requirement is:
\n is not working when I am using this text inserted in the same line.
How can I check duplicate username?
If I found username then how can I update user points?
I googled last 2 hours but not getting any solution. I have no idea about this problem.
This should work for you:
First use file() to read your file into an array. Then you can use array_map() to loop through each line and explode() it by | as delimiter. After this you can use array_column() to get the username as key for the points as value. Like this:
Array
(
[chinmay] => 1200
[john] => 200
[sanjib] => 480
[debasish] => 541
[chinmayx] => 200
)
With the array you can simply check if the username already exists or not. If not add it to the array and then add the points to it.
After adding the points to the username you can change your data back in the same format and save it with file_put_contents().
Full code:
<?php
$lines = file("test.txt", FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$usernames = array_column(array_map(function($v){
return explode("|", $v);
}, $lines), 1, 0);
$username = "chinmayx";
$points = 200;
if(!isset($usernames[$username]))
$usernames[$username] = 0;
$usernames[$username] += $points;
foreach($usernames as $k => $v)
$data[] = "$k|$v" . PHP_EOL;
file_put_contents("test.txt", $data);
?>
EDIT:
If you have PHP under 5.5 just replace:
$usernames = array_column(array_map(function($v){
return explode("|", $v);
}, $lines), 1, 0);
with this:
$lines = array_map(function($v){
return explode("|", $v);
}, $lines);
$usernames = array_combine(
array_map(function($v){
return $v[0];
}, $lines),
array_map(function($v){
return $v[1];
}, $lines)
);
Also if you want to get the TOP 10 users, just rsort() your array and then take an array_slice() of the first 10 elements, e.g.
rsort($usernames);
$topUsers = array_slice($usernames, 0, 10);
print_r($topUsers);
To get the \n working use the PHP_EOL as in another answer
$txt = $username."|".$points.PHP_EOL;
To update the user found in the text file go through following link
how to replace a particular line in a text file using php?
you should use PHP_EOL instead of "\n" which also depends on your OS
$txt = $username."|".$points.PHP_EOL;
for checking userName, just use:
//this works because $file is String because of fread()
if (strpos($file,$username) !== false) {
echo 'user exists';
}
for replacing you'll need regex or use strpos position (which returns position of name in string) and advance the pointer by count($username)+1 and search from there for newline, all this string between that, replace with new points
Try to use preg_match:
$file = fopen("score.txt", "r");
while (!feof($file)) {
preg_match("/^$username|(.*?)$/", $file, $array);
var_dump($array);
}
but I think it's better to use MySQL :)

PHP Counting delimited values in text file that are all on the same line

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";
}

Be sure to have unique array entry

I have a file which contains something like :
toto;145
titi;7
tata;28
I explode this file to have an array.
I am able to display the data with that code :
foreach ($lines as $line_num => $line) {
$tab = explode(";",$line);
//erase return line
$tab[1]=preg_replace('/[\r\n]+/', "", $tab[1]);
echo $tab[0]; //toto //titi //tata
echo $tab[1]; //145 //7 //28
}
I want to be sure that data contained in each $tab[0] and $tab[1] is unique.
For example, I want a "throw new Exception" if file is like :
toto;145
titi;7
tutu;7
tata;28
or like :
toto;145
tata;7
tata;28
How can I do that ?
Convert your file to array with file(), and convert to associative array with additional duplication checking.
$lines = file('file.txt', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$tab = array();
foreach ($lines as $line) {
list($key, $val) = explode(';', $line);
if (array_key_exists($key, $tab) || in_array($val, $tab)) {
// throw exception
} else {
$tab[$key] = $val;
}
}
Store them as key => value pairs in an array, and check whether each key or value already exists in your array as you are looping through the file. You can check for an existing key with array_key_exists and an existing value with in_array.
One simple is using array_unique, save the parts (tab[0] and tab[1]) into two separate arrays after you explode, name them for example $col1 and $col2 and then, you could do this simple test:
<?php
if (count(array_unique($col1)) != count($col1))
echo "arrays are different; not unique";
?>
PHP will turn your array parts into unique, if duplicated entrys exist, so if the size of the new array differs from the original, it means that it was not unique.
//contrived file contents
$file_contents = "
toto;145
titi;7
tutu;7
tata;28";
//split into lines and set up some left/right value trackers
$lines = preg_split('/\n/', trim($file_contents));
$left = $right = array();
//split each line into two parts and log left and right part
foreach($lines as $line) {
$splitter = explode(';', preg_replace('/\r\n/', '', $line));
array_push($left, $splitter[0]);
array_push($right, $splitter[1]);
}
//sanitise left and right parts into just unique entries
$left = array_unique($left);
$right = array_unique($right);
//if we end up with fewer left or right entries than the number of lines, error...
if (count($left) < count($lines) || count($right) < count($lines))
die('error');
Use associative arrays with keys "toto", "tata" etc.
To check whether a key exists you can use array_key_exists or isset.
BTW. Instead of preg_replace('/[\r\n]+/', "", $tab[1]), try trim (or even rtrim).
While you're traversing the array add the values to an existing array, i.e. placeholder, which will be used to check if the value exists or not via in_array().
<?php
$lines = 'toto;145 titi;7 tutu;7 tata;28';
$results = array();
foreach ($lines as $line_num => $line) {
$tab = explode(";",$line);
//erase return line
$tab[1]=preg_replace('/[\r\n]+/', "", $tab[1]);
if(!in_array($tab[0]) && !in_array($tab[1])){
array_push($results, $tab[0], $tab[1]);
}else{
echo "value exists!";
die(); // Remove/modify for different exception handling
}
}
?>

Categories