Method to speed up reading the contents of a file - php

In a script I'm having I'm pulling a csv from a remote server using ftp. I save this file locally and then open the file. I loop through all the contents of the file matching a certain value against it. If it matches, the script can continue.
Enough talking. Lets show some code...
$filename = 'ftp://.....';
$localCsv = '/tmp/'.date('Ymd').'.csv';
if (!file_exists($localCsv)) {
$content = file_get_contents($filename);
file_put_contents($localCsv, $content);
}
Now that we have the file created. We can continue to loop.
$handle = fopen($localCsv, "r");
while(!feof($handle)) {
$rows[] = fgets($handle);
}
fclose($handle);
$results = array();
foreach ($rows as $rid => $row) {
$columns = explode("\t", $row);
$results[$columns[2]] = $columns;
}
if (array_key_exists($searchValue, $results)) {
... Continue script ...
}
There is just one tiny little problem with this method. It's so slow it's almost going backwards.

Heres all baked together, maybe thats faster?
$handle = fopen($localCsv, "r");
$results = array();
while(!feof($handle)) {
$columns = explode("\t", fgets($handle));
$results[$columns[2]] = $columns;
if ($columns[2] == $searchValue) {
//SEARCH HIT
}
}
fclose($handle);
If thats not working you could try the csv-specific methods that are in PHP

Related

How to sort a CSV file by a column and then sort by a second column, then saving the CSV file

I'm looking to read a CSV export file with PHP. I have access to the File Path Variable called $file_path.
How would I sort the CSV export file by a specific column and then sort it again by a second column? and then save the CSV file to the same file name and file path.
UPDATE:
I got it to read the CSV, then sort it and also save it to the CSV. However, it's also sorting the headers. I am trying to use array_shift and array_unshift but when I use array_shift with a multi-layer array, I am getting an error. (unshift works fine though).
function wp_all_export_after_export($export_id, $exportObj)
{
// Check whether "Secure Mode" is enabled in All Export -> Settings
$is_secure_export = PMXE_Plugin::getInstance()->getOption('secure');
if (!$is_secure_export) {
$filepath = get_attached_file($exportObj->attch_id);
} else {
$filepath = wp_all_export_get_absolute_path($exportObj->options['filepath']);
}
$handle = fopen($filepath, 'r') or die('cannot read file');
$binNumber = array();
$category = array();
$rows = array();
$header = array();
//build array of binNumbers, Categories, and array of rows
while (false != ( $row = fgetcsv($handle, 0, ',') )) {
$binNumber[] = $row[3];
$category[] = $row[1];
$rows[] = $row;
}
fclose($handle);
$header = $rows[0];
array_shift($rows);
//sort array of rows by BinNumber & then Category using our arrays
array_multisort($binNumber,SORT_ASC, $category, SORT_ASC, $rows);
array_unshift($rows,$header);
$file = fopen($filepath,"w");
foreach ($rows as $line) {
fputcsv($file, $line);
}
fclose($file);
}
add_action('pmxe_after_export', 'wp_all_export_after_export', 10, 2);

PHP update big CSV files efficently

so basically my objective here is pretty simple. I have an big CSV inventory file with about 400k lines/items and I am receiving a csvstock file every couple minutes. I am trying to find an efficent and fast way to transfer the new stock count from the gathered stock-feed and update the stock on my inventory file. I created an array from the stock-feed, looping trough my inventory csv file and if the sku from the stock-feed matches with a sku of my inventory file, I am replacing the stock count from the stock-feed to my inventory file.
But the efficency here is really bad, takes years to update those 400k lines.
Any idea for a good efficent way to update my inventory csv with the data from my stock-feed?
Maybe PHP is not the right to work here with, if so, any other tips on how to handle it fast and efficient ?
That is my stinky code so far:
<?php
$rows = array_map('str_getcsv', file('stock-feed.csv') , [","]);
$header = array_shift($rows);
$csv = array();
foreach ($rows as $row)
{
$csv[] = array_combine($header, $row);
}
$row = 1;
$filedone = fopen("updatedStockInventory.csv", "w");
$fileName = "Inventory.csv";
$file = fopen($fileName, "r");
while (($column = fgetcsv($file, 10000, "|")) !== false)
{
if ($row == 0)
{
}
else
{
$key = array_search($column[2], array_column($csv, 'sku'));
$stock = $csv[$key]['stock'];
if ($key != "")
{
//Write line with new stock count
}
else
{
//skip
}
fputs($filedone, $line);
}
$row++;
}
?>

deleting matches from text file in php

Consider a txt file of a list of items
qqqqqq
eeeeee
dddddd
hhhhhh
dddddd
hhhhhh
999999
And some of the items in the list are duplicates. how do I output a using php a text file where anything that is duplicated is removed.
the result:
qqqqqq
eeeeee
999999
You can use array_unique
and then right the content back
$file = fopen("filename.txt", "r");
$members = array();
while (!feof($file)) {
$members[] = fgets($file);
}
fclose($file);
$unique_members = array();
$unique_members = array_unique($members);
var_dump($unique_members);
//write the content back to the file
The above solution was for removing the duplicates only and make them unique. Thanks to nhahtdh for pointing it out.
$count_members = array_count_values($members);
foreach($count_members as $key=>$value)
{
if($value == 1)
//write it to the file
}
So you will not need the array_unique stuff
Sorry again
<?php
$file = file_get_contents('file.txt'); //get file to string
$row_array = explode("\n",$file); //cut string to rows by new line
$row_array = array_count_values(array_filter($row_array));
foreach ($row_array as $key=>$counts) {
if ($counts==1)
$no_duplicates[] = $key;
}
//do what You want
echo '<pre>';
print_r($no_duplicates);
file_put_contents('no_duplicates.txt',$no_duplicates); //write to file. If file don't exist. Create it.

Problem with the fgetcsv() in php

I have the following piece of code to parse a csv file. After that I am displaying it. The .csv file is displaying perfectly on my local machine but on the server after clicking on upload a blank page is displaying.
function uploadTrainees()
{
$csv = array();
$tmpName = $_FILES['csv']['tmp_name'];
//echo $tmpName;
//ini_set('auto_detect_line_endings',true);
$fp = fopen($tmpName,'r');
$fields = array('delegate_title', 'delegate_firstname', 'delegate_lastname', 'delegate_jobtitle', 'delegate_email', 'delegate_phone', 'is_bringing_own_laptop');
$records = array();
while ($record = fgetcsv($fp,1000,','))
{
$records[] = array_combine($fields, $record);
}
fclose($fp);
}
Help me to solve this issue.
What version of PHP is the live server running?
The function array_combine() is only in PHP5
Edit
There is a function here to do this - http://snipplr.com/view/4918/arraycombine-for-php4/
if (!function_exists('array_combine'))
{
function array_combine($arr1,$arr2) {
$out = array();
foreach ($arr1 as $key1 => $value1) {
$out[$value1] = $arr2[$key1];
}
return $out;
}
}

PHP: How can I get the contents of a CSV file into a MySQL database row by row?

How can I get the contents of a CSV file into a MySQL database row by row? Ive tried a few methods but can never get more than one row returned, using fgetcsv. One method I've tried that seemed to come so close to working:
$fileName = $_FILES['SpecialFile']['name'];
$tmpName = $_FILES['SpecialFile']['tmp_name'];
$fileSize = $_FILES['SpecialFile']['size'];
if(!$fileSize)
{
echo "File is empty.\n";
exit;
}
$fileType = $_FILES['SpecialFile']['type'];
$file = fopen($tmpName, 'r');
if(!$file)
{
echo "Error opening data file.\n";
exit;
}
while(!feof($file))
{
$data = str_replace('"','/"',fgetcsv($file, filesize($tmpName), ","));
$linemysql = implode("','",$data);
$query = "INSERT INTO $databasetable VALUES ('$linemysql')";
return mysql_query($query);
}
fclose($file);
only enters one row, but if I print_r $data it returns all the rows. How do I get it to insert all th rows?
Another method:
$data = str_getcsv($csvcontent,"\r\n","'","");
foreach($data as &$Row)
{
$linearray = str_getcsv($Row,',',''); //parse the items in rows
$linemysql = implode("','",$linearray);
echo $query = "INSERT INTO $databasetable VALUES ('$linemysql')";
}
This almost works too, but there is text within the csv that also contains new lines, so I dont know howto split the actual rows and not the new lines in the text as well.??
this function return an array from csv file
function CSVImport($file) {
$handle = fopen($file, 'r');
if (!$handle)
die('Cannot open file.');
$rows = array();
//Read the file as csv
while (($data = fgetcsv($handle, 1000, ";")) !== FALSE) {
$rows[] = $data
}
fclose($handle);
return $rows;
}
// this will return an array
// make some logic to read the array and save it
$csvArray = CSVImport($tmpName);
if (count($csvArray)) {
foreach ($csvArray as $key => $value) {
// $value is a row of adata
}
}
I think this is what you are looking for.
function getCSVcontent($filePath) {
$csv_content = fopen($filePath, 'r');
while (!feof($csv_content)) {
$rows[] = fgetcsv($csv_content,1000,";");
}
fclose($csv_content);
return $rows;
}
Make sure that you new line separator is ";" or give the correct one to fgetcsv(). Regards.

Categories