fgetcsv throwing error when calling from CLI - php

Can run my php file fine when checking it via browser, but throws an infinite loop error when run via CLI:
fgetcsv() expects parameter 1 to be resource, boolean given on line 30 (while line)
Code:
readCSV("feeds/data.csv");
function readCSV($csvFile) {
$count = 0; //for counting array objects
$storedQuotes = array();
$handle = fopen($csvFile, 'r');
//fgetcsv($file, 1000, ","); //remove first line
while (($line = fgetcsv($handle, 1000, ",")) !== FALSE) {
$quote = $line[2];
$author = $line[1];
//add element to $csv_arr with $quote and $author
$csv_arr[]=array(
"quote" => $quote,
"author" => $author
);
}
fclose($file);
}
How can I get my program to run via php cli?

Check if $handle is a resource (or is false) first. For example:
$handle = fopen($csvFile, 'r');
if(false !=== $handle) {
// do while{} here
}
else {
echo "Could not open $csvFile for reading";
}
Also, in CLI, your file paths are different. So you need to be more explicit. The easiest way to do this, if $csvFile is located in a relative path to the script, is to define the path such as:
__DIR__ . "feeds/data.csv"

It seems like your PHP code doesn't find the file (because fopen returns false).
I think you should use full path instead of relative since you are running it in cmd.
You should set your path like the following:
readcsv(dirname(__FILE__).'/feeds/data.csv');
It should work if "feeds" directory is in the same directory as your PHP file.

Related

PHP Cron Read CSV from URL and Convert to Array

I am trying to develop email system that need to be send every month. So i need to build cron job file from php. Anyone know how to read file CSV or Excel file from url such as:
http://yourdomain.com/cron.php?file=http://google.com/monthly.csv
I am stuck when try to read file from url.
This is my recent code:
<?php
$url = 'http://www1.intranet.com/reportingtool.asp?settings=var&export=ok';
$tmpfname = tempnam(sys_get_temp_dir());
file_put_contents(
$tmpfname,
file_get_contents($url)
);
?>
If you're dealing with remote files, you should always keep in mind that
The connection between you and the remote can break, and you won't get the full file content;
The file can be too big to read it on-the-fly.
In both cases, file_get_contents() is not a very good thing to use: you should consider cURL functions for that. However, if the concerns above are negligible, you should be okay with the following (as the example here suggests):
$url = 'http://www1.intranet.com/reportingtool.asp?settings=var&export=ok';
$tmpfname = tempnam(sys_get_temp_dir());
file_put_contents(
$tmpfname,
file_get_contents($url)
);
if (($handle = fopen($tmpfname, "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
// Do something with $data, which comes in
// as an array of values from the current CSV line.
}
}
Someone would need one more example, so leaving it here:
$dataSource can be any file on drive or just online link to parse csv.
private array $data = [];
private string $dataSource = "https://any.csv";
if (($open = fopen($dataSource, 'rb')) !== false)
{
while (($data = fgetcsv($open, 1000, ";")) !== false)
{
$data[] = $data;
}
fclose($open);
}

Push file to array in loop

EDIT after all the answers, i updated the function, and it works
I read out a importfolder. In this folder are many different files available.
Step: I read the folder and add the files to a array
Step: I open every file and try to import
When i cant import a file, then this happens, when another file in this row have to be imported first.
Example: If I open a file "message to a address", this could not be imported, when the address are not added into the database. But in some other file of this filelist is the "create address"-file. When this is created, then it is good, when the "message to a address" will be added to the filelistarray on the end.
My Code give me an offset problem:
function importData( $path, $db, $mail )
{
//Get available Importfiles
$filelist = getFilelist( $path );
for ($i = 0; $i < count($filelist); $i++)
{
$filename = $path . "/" . $filelist[$i];
$file = fopen( $filename,"r" );
while(!feof( $file )) {
$items = explode( ";", fgets( $file ) );
//Get messagetyp
if( strtolower(trim($items[0])) == "nachrichtentyp" )
{
$messagetyp = $items[1];
break;
}
}
fclose($file);
if ( $messagetyp )
{
$f = "import" . $messagetyp;
if( !$f($filename, $db, $mail) )
{
array_push($filelist, $filelist[$i]);
}
}
}
}
This my error, when I push the element to the the filelist-array
PHP Warning: feof() expects parameter 1 to be resource, boolean given in /var/www/symfony/importscript/import.php on line 37
PHP Warning: fgets() expects parameter 1 to be resource, boolean given in /var/www/symfony/importscript/import.php on line 38
According to your errors, problem lies not in array_push but in fopen():
$file = fopen( $filename,"r" );
If php fails to open that file, variable $file will be set to false and because of that feof() and fgets() will give you errors.
You definitely should check if fopen returns another value than FALSE, maybe one of the files does not exist or you are restricted.

How can I split a CSV file in PHP?

I have a big CSV file. I want to separate this file into separate files based on the value in one of the fields.
This is what I have done. Using fgetcsv I convert the CSV into an array, and using in_array, I check the content and display if it contains the string within the array.
I will be getting the comparison string from another text file iteratively to check whether it is contained in the csv. In this case I have specified it as "Testing".
Below is the code:
if (($handle = fopen("test.csv", "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
if(in_array("Testing", $data))
{
var_dump($data);
}
}
fclose($handle);
}
This is working, but now I am stuck. How do I write $data into another CSV file? Or is there a better way to do this?
It's actually pretty simple and if the string just has to be on the line, you don't even need fgetcsv. Just
$srcFile = new SplFileObject('test.csv');
$destFile = new SplFileObject('new.csv', 'w+');
foreach ($srcFile as $line) {
if (strpos($line, 'testing') !== FALSE) {
$destFile->fwrite($line);
}
}
This will create two file objects. The first one holding the content of your source file. The second one creating an all new file for the lines containing your search string. We then just iterate over each line and check if the search string exists. If so, we write it to destination file.
The source file will not be touched this way. If you want to have one file with the search string and one file without, just create a third SplFileObject and add an else block to the if writing the line to that one then. In the end, delete the source csv file.
You have to do some tricky thing I am providing some basic idea for doing so, here is the code:
//opening file
if ($fp = fopen('log.csv', 'r')) {
$line_number = 0;
//loop for Reading file as line by line csv file
while ($line = fgetcsv($fp, 0, ';')) {
if ($line_number++ == 0) {
continue;
}
//array data string to make possible to provide file name
//according to column name required
$date = explode(' ', $line[0]);
//Change the column name according to your needs
$file = $date[0] .'.log';
file_put_contents(
//change the folder name according to your needs
'monthly/'. $file,
//printing data in appended file
implode(';', $line) ."\n",
FILE_APPEND
);
}
//closing file
fclose($fp);
}
It reads CSV file line by line, extracts date part from the first column and creates new file and appends data to it.
Note:
folder "monthly" must be writable

PHP's fopen is terminally failing

Okay, I have GOT to be missing something totally rudimentary here.
I have an extremely simple use of PHP's fopen function, but for some reason, it will not open the file no matter what I do.
The odd part about this is that I use fopen in another function in the same script and it's working perfectly. I'm using the fclose in both functions. So, I know it's not a matter of a rogue file handle.
I have confirmed the file's path and the existence of the target file also.
I'm running the script at the command-line as root, so I know it's not apache that's the cause. And since I am running the script as root, I am fairly confident that permissions are not the issue.
So, what on earth am I missing here?
function get_file_list() {
$file = '/home/site/tmp/return_files_list.txt';
$fp = fopen($file, 'r') or die("Could not open file: /home/site/tmp/return_files_list.txt for reading.\n");
$files_list = array();
while($line = fgets($fp)) {
$files_list[] = $line;
}
fclose($fp);
return $files_list;
}
function num_records_in_file($filename) {
$fp = fopen( $filename, 'r' ); # or die("Could not open file: $filename\n");
$counter = 0;
if ($fp) {
while (!feof( $fp )) {
$line = fgets( $fp );
$arr = explode( '|', $line );
if (( ( $arr[0] != 'HDR' && $arr[0] != 'TRL' ) && $arr[0] != '' )) {
++$counter;
continue;
}
}
}
fclose( $fp );
return $counter;
}
As requested, here's both functions. The second function is passed an absolute path to the file. That is what I used to confirm that the file is there and that the path is correct.
Wow! Well, I figured it out.
On a whim, I decided to try trimming the file name. Apparently, it was carrying some whitespace or something at the end of the filename. So, when it tried to open the file, it couldn't due to looking for $filename +
Learn something new everyday, I guess.

Define array of file locations, parse and replace. Where's my error?

I'm trying to define an array with a list of file urls, and then have each file parsed and if a predefined string is found, for that string to be replaced. For some reason what I have isn't working, I'm not sure what's incorrect:
<?php
$htF = array('/home/folder/file.extension', '/home/folder/file.extension', '/home/folder/file.extension', '/home/folder/file.extension', '/home/folder/file.extension');
function update() {
global $htF;
$handle = fopen($htF, "r");
if ($handle) {
$previous_line = $content = '';
while (!feof($handle)) {
$current_line = fgets($handle);
if(stripos($previous_line,'PREDEFINED SENTENCE') !== FALSE)
{
$output = shell_exec('URL.COM');
if(preg_match('#([0-9]{1,3}\.){3}[0-9]{1,3}#',$output,$matches))
{
$content .= 'PREDEFINED SENTENCE '.$matches[0]."\n";
}
}else{
$content .= $current_line;
}
$previous_line = $current_line;
}
fclose($handle);
$tempFile = tempnam('/tmp','allow_');
$fp = fopen($tempFile, 'w');
fwrite($fp, $content);
fclose($fp);
rename($tempFile,$htF);
chown($htF,'admin');
chmod($htF,'0644');
}
}
array_walk($htF, 'update');
?>
Any help would be massively appreciated!
Do you have permissions to open the file?
Do you have permissions to write to /tmp ?
Do you have permissions to write to the destination file or folder?
Do you have permissions to chown?
Have you checked your regex? Try something like http://regexpal.com/ to see if it's valid.
Try adding error messages or throw Exceptions for all of the fail conditions for these.
there's this line:
if(stripos($previous_line,'PREDEFINED SENTENCE') !== FALSE)
and I think you just want a != in there. Yes?
You're using $htF within the update function as global, which means you're trying to fopen() an array.
$fh = fopen($htF, 'r');
is going to get parsed as
$fh = fopen('Array', 'r');
and return false, unless you happen to have a file named 'Array'.
You've also not specified any parameters for your function, so array_walk cannot pass in the array element it's dealing with at the time.

Categories