I need to set a dynamic file name in PHP. So I wrote a small example script to represent the problems I am facing.
When I run the following script, I get the following erroneous output, and the file created is just named .csv while it should be named 0101.csv
OUTPUT:
Notice: Undefined variable: 65 in C:\xampp\htdocs\testsEight.php on line 5
Notice: Undefined variable: 65 in C:\xampp\htdocs\testsEight.php on line 7
Array ( [0] => BillClinton )
Why does it call the variable as 65 rather than $the_id? I am trying to follow these guidelines. In the following code, I also tried to replace it by ${$the_id}, no luck!
CODE:
<?php
$type = 'BillClinton';
$the_id = 0101;
file_put_contents ( 'C:/'.$$the_id.'.csv' , $type ."," , FILE_APPEND );
$file = fopen('C:/'.$$the_id.'.csv', 'r');
$line = fgetcsv($file);
array_pop($line);
if ($line !== FALSE) {
//$line is an array of the csv elements in a line. The fgetcsv() function parses a line from an open file, checking for CSV fields.The fgetcsv() function stops returning on a new line, at the specified length, or at EOF, whichever comes first.
print_r($line);//check
} else {echo 'FALSE';}
Please help me fix this.
You're using two $ in $$the_id and one in $the_id = 0101;
"Why does it call the variable as 65"
The leading zero is treating 0101 as an octal, so wrap it in quotes $the_id = "0101";
You had extra $ in $$the_id which lead to call the reference of $the_id intead of variable name the_id. So you need to erase that. Code will be as follow;
<?php
$type = 'BillClinton';
$the_id = 0101;
file_put_contents ( 'C:/'.$the_id.'.csv' , $type ."," , FILE_APPEND );
$file = fopen('C:/'.$the_id.'.csv', 'r');
$line = fgetcsv($file);
array_pop($line);
if ($line !== FALSE) {
//$line is an array of the csv elements in a line. The fgetcsv() function parses a line from an open file, checking for CSV fields.The fgetcsv() function stops returning on a new line, at the specified length, or at EOF, whichever comes first.
print_r($line);//check
} else {echo 'FALSE';}
for more details, you can look in PHP documentation
Firstly, your example is wrong. PHP will never allow you to define integer and not even "string-casted" integers as a variable name.
The only problem in your script is that you are using double dollar signs, which is a refference to $0101 (assuming the $the_id is 0101 string or integer, doesn't matter).
The simple solution is to remove your double dollar signs in:
file_put_contents ( 'C:/'.$the_id.'.csv' , $type ."," , FILE_APPEND );
$file = fopen('C:/'.$the_id.'.csv', 'r');
The idea behind this is that a variable's name can be variable. And that's how your problem rose.
$a = 'hello';
$$a = 'world';
echo $hello; // will output 'world';
Regards.
Related
Could anyone give me some ideas or solution for toggling comments in file?
To read value and toggle comment/uncomment in that line where value resides.
For example, I would like to include class Model and initialize it.
In some file there are prepared includes and initializations:
//include('foo/Model.php');
//$model = new Model();
Function is needed, for those who can not understand what the question is.
How to uncomment?
Thanks for adding more insights to your question! Actually it's a pretty interesting one.
As far as I understand you're looking for a dynamic way to comment/uncomment lines inside a file.
So let's define our parameters first:
We want to manipulate a specific file (we need the filename)
We want to toggle specific line numbers inside this file (list of line numbers)
function file_toggler(string $file, array $lineNumbers)
With this in mind I we need to read a file and split their lines into line numbers. PHP provides a handy function for this called file().
file(): Returns the file in an array. Each element of the array corresponds to a line in the file, with the newline still attached.
With this in mind we have everything what we need to write a function:
<?php
function file_toggler(string $file, array $lineNumbers)
{
// normalize because file() starts with 0 and
// a regular user would use (1) as the first number
$lineNumbers = array_map(function ($number) {
return $number - 1;
}, $lineNumbers);
// get all lines and trim them because
// file() keeps newlines inside each line
$lines = array_map('trim', file($file));
// now we can take the line numbers and
// check if it starts with a comment.
foreach ($lineNumbers as $lineNumber) {
$line = trim($lines[$lineNumber]);
if (substr($line, 0, 2) == '//') {
$line = substr($line, 2);
} else {
$line = '//' . $line;
}
// replace the lines with the toggled value
$lines[$lineNumber] = $line;
}
// finally we write the lines to the file
// I'm using implode() which will append a "\n" to every
// entry inside the array and return it as a string.
file_put_contents($file, implode(PHP_EOL, $lines));
}
toggleFileComments(__DIR__ . '/file1.php', [3, 4]);
Hope it helps :-)
you helped me so much time but now to this Problem i didn´t find a solution yet.
I have two csv which i had to compare and get the differences.
Both csv looks like this:
https://stackoverflow.com
https://google.com
Both files are about 10 MB
Till now i make this:
array1 = array_map('str_getcsv', file(file1));
array2 = array_map('str_getcsv', file(file2));
$diff = array_diff(array_map('serialize',$array1), array_map('serialize',$array2 ));
it works very nice so long as i have unlimited memory.
And thats the problem;-) i don´t have unlimited memory because the server is not the same as befor.
So now the question is:
How can i reduce the memory_usage of it or how can i compare two files.
Please don´t think of filesize or so what.
I need the real differences of the file.
Like in one file it stands
https://stackoverflow.com
and in the other
https://google.com
so the difference is both:-)
thanks for your help guys
Read file1 into the keys of an associative array. Then read file2 line by line, removing those entries from the array.
$file1 = array_flip(file("file1.csv", FILE_IGNORE_NEW_LINES));
$fd2 = fopen("file2.csv");
$diff = array();
while ($line = fgets($fd2)) {
$line = str_replace("\n", "", $line); // remove trailing newline
if (!array_key_exists($line, $file1)) {
// line is only in file2, add it to result
$diff[] = $line;
} else {
// line is in both files, remove it from $file1
unset($file1[$line]);
}
}
fclose($fd2);
// Remaining keys in $file1 are unique to that file
$diff += array_keys($file1);
If reading the first file into an array and then flipping it is too much memory, you could do that with an fgets() loop as well (but the garbage collector should clean up the temporary array created by file()).
Well, my question is very simple, but I didn't find the proper answer in nowhere. What I need is to find a way that reads a .txt file, and if there's a duplicated line, remove ALL of them, not preserving one. For example, in a .txt contains the following:
1234
1233
1232
1234
The output should be:
1233
1232
Because the code has to delete the duplicated line, all of them. I searched all the web, but it always point to answers that removes duplicated lines but preserve one of them, like this, this or that.
I'm afraid that the only way to do this is to read the x line and check the whole .txt, if it finds an equal result, delete, and delete the x line too. If not, change to the next line. But the .txt file I'm checking has 50 milions lines (~900Mb), I don't know how much memory I need to do this kind of task, so I appreciate some help here.
Read the file line by line, and use the line contents as the key of an associative array whose values are a count of the number of times the line appears. After you're done, write out all the lines whose value is only 1. This will require as much memory as all the unique lines.
$lines = array();
$fd = fopen("inputfile.txdt", "r");
while ($line = fgets($fd)) {
$line = rtrim($line, "\r\n"); // ignore the newline
if (array_key_exists($line, $lines)) {
$lines[$line]++;
} else {
$lines[$line] = 1;
}
}
fclose($fd);
$fd = fopen("outputfile.txt", "w");
foreach ($lines as $line => $count) {
if ($count == 1) {
fputs($fd, "$line" . PHP_EOL); // add the newlines back
}
}
I doubt there is one and only one function that does all of what you want to do. So, this breaks it down into steps...
First, can we load a file directly into an array? See the documentation for the file command
$lines = file('mytextfile.txt');
Now, I have all of the lines in an array. I want to count how many of each entry I have. See the documentation for the array_count_values command.
$counts = array_count_values($lines);
Now, I can easily loop through the array and delete any entries where the count>1
foreach($counts as $value=>$cnt)
if($cnt>1)
unset($counts[$value]);
Now, I can turn the array keys (which are the values) into an array.
$nondupes = array_keys($counts);
Finally, I can write the contents out to a file.
file_put_contents('myoutputfile.txt', $nondupes);
I think I have a solution far more elegant:
$array = array('1', '1', '2', '2', '3', '4'); // array with some unique values, some not unique
$array_count_result = array_count_values($array); // count values occurences
$result = array_keys(array_filter($array_count_result, function ($value) { return ($value == 1); })); // filter and isolate only unique values
print_r($result);
gives:
Array
(
[0] => 3
[1] => 4
)
I am getting this PHP error:
PHP Notice: Undefined offset: 1
Here is the PHP code that throws it:
$file_handle = fopen($path."/Summary/data.txt","r"); //open text file
$data = array(); // create new array map
while (!feof($file_handle) ) {
$line_of_text = fgets($file_handle); // read in each line
$parts = array_map('trim', explode(':', $line_of_text, 2));
// separates line_of_text by ':' trim strings for extra space
$data[$parts[0]] = $parts[1];
// map the resulting parts into array
//$results('NAME_BEFORE_:') = VALUE_AFTER_:
}
What does this error mean? What causes this error?
Change
$data[$parts[0]] = $parts[1];
to
if ( ! isset($parts[1])) {
$parts[1] = null;
}
$data[$parts[0]] = $parts[1];
or simply:
$data[$parts[0]] = isset($parts[1]) ? $parts[1] : null;
Not every line of your file has a colon in it and therefore explode on it returns an array of size 1.
According to php.net possible return values from explode:
Returns an array of strings created by splitting the string parameter on boundaries formed by the delimiter.
If delimiter is an empty string (""), explode() will return FALSE. If delimiter contains a value that is not contained in string and a negative limit is used, then an empty array will be returned, otherwise an array containing string will be returned.
How to reproduce the above error in PHP:
php> $yarr = array(3 => 'c', 4 => 'd');
php> echo $yarr[4];
d
php> echo $yarr[1];
PHP Notice: Undefined offset: 1 in
/usr/local/lib/python2.7/dist-packages/phpsh/phpsh.php(578) :
eval()'d code on line 1
What does that error message mean?
It means the php compiler looked for the key 1 and ran the hash against it and didn't find any value associated with it then said Undefined offset: 1
How do I make that error go away?
Ask the array if the key exists before returning its value like this:
php> echo array_key_exists(1, $yarr);
php> echo array_key_exists(4, $yarr);
1
If the array does not contain your key, don't ask for its value. Although this solution makes double-work for your program to "check if it's there" and then "go get it".
Alternative solution that's faster:
If getting a missing key is an exceptional circumstance caused by an error, it's faster to just get the value (as in echo $yarr[1];), and catch that offset error and handle it like this: https://stackoverflow.com/a/5373824/445131
Update in 2020 in Php7:
there is a better way to do this using the Null coalescing operator by just doing the following:
$data[$parts[0]] = $parts[1] ?? null;
This is a "PHP Notice", so you could in theory ignore it. Change php.ini:
error_reporting = E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED
To
error_reporting = E_ALL & ~E_NOTICE
This show all errors, except for notices.
my quickest solution was to minus 1 to the length of the array as
$len = count($data);
for($i=1; $i<=$len-1;$i++){
echo $data[$i];
}
my offset was always the last value if the count was 140 then it will say offset 140 but after using the minus 1 everything was fine
The ideal solution would be as below. You won't miss the values from 0 to n.
$len=count($data);
for($i=0;$i<$len;$i++)
echo $data[$i]. "<br>";
In your code:
$parts = array_map('trim', explode(':', $line_of_text, 2));
You have ":" as separator. If you use another separator in file, then you will get an "Undefined offset: 1" but not "Undefined offset: 0" All information will be in $parts[0] but no information in $parts[1] or [2] etc. Try to echo $part[0]; echo $part[1]; you will see the information.
I just recently had this issue and I didn't even believe it was my mistype:
Array("Semester has been set as active!", true)
Array("Failed to set semester as active!". false)
And actually it was! I just accidentally typed "." rather than ","...
The output of the error, is because you call an index of the Array that does not exist, for example
$arr = Array(1,2,3);
echo $arr[3];
// Error PHP Notice: Undefined offset: 1 pointer 3 does not exist, the array only has 3 elements but starts at 0 to 2, not 3!
So given this simple example:
<?php
$memory = fopen('php://memory', 'r+');
fwrite($memory, 'asdf', 4);
$value = fread($memory, 3);
var_dump($value);
I was expecting $value to contain the string "asd" but instead I get an empty string. Is there anything obvious about this example that needs to change? Is my expectation incorrect? If $value should indeed contain "asd" what might cause this to happen (a configuration/php.ini issue perhaps)?
Since the internal pointer of the stream is at index 4 after you write the data, you need to fseek back to the beginning of your stream:
// fwrite
fseek($memory, 0); // same as rewind($memory);
// fread
Alternatively, this would also work (and is basically the equivalent to fseek($memory, 0);):
rewind($memory);