Getting special characters while reading a csv file in php - php

I have a space separated csv file. I am trying to read using following method:
$file = fopen('/var/www/html/my.csv', 'r');
while (($line = fgetcsv($file,0,"\t")) !== FALSE) {
$header_count = 0;
// $final_data = array();
if ( $count == 0 )
{
foreach ($line as $data) {
$header[$header_count] = $data;
$header_count++;
}
}
else
{
// print_r($line);
foreach ($line as $data) {
$final_data[$count-1][$header[$header_count]] = $data;
$header_count++;
}
}
$count++;
}
The file looks like:
id created ad
410699345585 11:12:29+05:30 ag:6061734588280
...
But, the reading output gives:
["��id"]=>
as id index. What am I doing wrong?

Related

PHP CSV duplicate values

I've got a csv file which contains product datas and prices from two distributors.
There are 67 keys in this file.
Now I want to search all EANs in this file which are twice available and then get the cheapest price.
After that delete the other higher price product line.
The CSV has a key for my merchant.
I made a test csv for easier view:
artno;name;ean;price;merchant
1;ipad;1654213154;499.00;merchant1
809;ipad;1654213154;439.00;merchant2
23;iphone;16777713154;899.00;merchant2
90;iphone;16777713154;799.00;merchant1
After the script runs through, the csv should look like (writing to new file):
artno;name;ean;price;merchant
809;ipad;1654213154;439.00;merchant2
90;iphone;16777713154;799.00;merchant1
I played around with fgetcsv, looping through the csv is not a problem, but how I can search for the ean in key 2?
$filename = './test.csv';
$file = fopen($filename, 'r');
$fileline = 1;
while (($data = fgetcsv($file, 0, ";")) !== FALSE) {
if($fileline == "1"){ $fileline++; continue; }
$search = $data[2];
$lines = file('./test.csv');
$line_number = false;
$count = 0;
while (list($key, $line) = each($lines) and !$line_number) {
$line_number = (strpos($line, $search) !== FALSE) ? $key : $line_number;
$count++;
}
if($count > 2){
echo "<pre>",print_r(str_getcsv($lines[$line_number], ";")),"</pre>";
}
}
I think this is what you are looking for:
<?php
$filename = './test.csv';
$file = fopen($filename, 'r');
$lines = file('./test.csv');
$headerArr = str_getcsv($lines[0], ";");
$finalrawData = [];
$cheapeastPriceByProduct = [];
$dataCounter = 0;
while (($data = fgetcsv($file, 0, ";")) !== FALSE) {
if($dataCounter > 0) {
$raw = str_getcsv($lines[$dataCounter], ";");
$tempArr = [];
foreach( $raw as $key => $val) {
$tempArr[$headerArr[$key]] = $val;
}
$finalrawData[] = $tempArr;
}
$dataCounter++;
}
foreach($finalrawData as $idx => $dataRow ) {
if(!isset($cheapeastPriceByProduct[$dataRow['name']])) {
$cheapeastPriceByProduct[$dataRow['name']] = $dataRow;
}
else {
if(((int)$dataRow['price'])< ((int)$cheapeastPriceByProduct[$dataRow['name']]['price'])) {
$cheapeastPriceByProduct[$dataRow['name']] = $dataRow;
}
}
}
echo "<pre>";
print_r($finalrawData);
print_r($cheapeastPriceByProduct);
I just added $finalData data array to store the parsed data and associated all rows with their header key counterpart then you can compare and filter data based on your criteria.

Add new columns for CSV file

I have tree arrays with different lengths, and I want to display each array in a column of my csv file. That's the php script file I am using but no success; I got the data duplicated.
The attempt I tried was to feed empty cells with an empty string so that I can have 3 columns with the same lengths.
$categories = get_categories( $args );
$categories_level_1 = array();
$categories_level_2 = array();
$categories_level_3 = array();
foreach ($categories as $cat ) {
$cat_level =count( get_ancestors($cat->term_id, 'category') );
if($cat_level == 0){
$categories_level_1[] = $cat;
}else{
if($cat_level == 1){
$categories_level_2[] = $cat;
}elseif($cat_level == 2){
$categories_level_3[] = $cat;
}
}
}
fputcsv($file, array(utf8_decode('Catégories level 1')));
$i=0;
foreach ($categories_level_1 as $category) {
$i++;
$categorie_name = array(rw_mb_convert_encoding($category->name));
fputcsv($file, $categorie_name );
print_flush("\n liine created");
}
while( $i < count($categories_level_2)){
$i++;
fputcsv($file, array(" "));
print_flush("\n liine vide created");
}
fclose($file);
$newCsvData = array();
foreach ($categories_level_2 as $cat) {
if (($handle = fopen($csv_file_path, "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
$data[] = rw_mb_convert_encoding($cat->name);
$newCsvData[] = $data;
}
fclose($handle);
}
}
$handle = fopen($csv_file_path, 'w');
foreach ($newCsvData as $line) {
fputcsv($handle, $line);
}
fclose($handle);
I should get my columns with the folowwing structure :
But in reality that's the result I got :

Convert csv in php and get unique value

I would like to convert a csv file that has duplicate contents and i would like to sum the quantity and extract the price without sum it.
file.csv :
code,qty,price
001,2,199
001,1,199
002,2,159
002,2,159
Actual php that sum the quantiy and get a result with unique value and total qty.
<?php
$tsvFile = new SplFileObject('file.csv');
$tsvFile->setFlags(SplFileObject::READ_CSV);
$tsvFile->setCsvControl("\t");
$file = fopen('file.csv', 'w');
$header = array('sku', 'qty');
fputcsv($file, $header, ',', '"');
foreach ($tsvFile as $line => $row) {
if ($line > 0) {
if (isset($newData[$row[0]])) {
$newData[$row[0]]+= $row[1];
} else {
$newData[$row[0]] = $row[1];
}
}
}
foreach ($newData as $key => $value) {
fputcsv($file, array($key, $value), ',', '"');
}
fclose($file);
?>
the result for this is:
code,qty
001,3
002,4
and i would like to add price, but without sum it.
The result i need is:
code,qty,price
001,3,199
002,4,159
I haven't tested this yet, but I think this is what you are looking for:
<?php
$tsvFile = new SplFileObject('file.csv');
$tsvFile->setFlags(SplFileObject::READ_CSV);
$tsvFile->setCsvControl("\t");
$file = fopen('file.csv', 'w');
$header = array('sku', 'qty');
fputcsv($file, $header, ',', '"');
foreach ($tsvFile as $line => $row) {
if ($line > 0) {
if(!isset($newData[$row[0]])) {
$newData[$row[0]] = array('qty'=>0, 'price'=>$row[2]);
}
$newData[$row[0]]['qty'] += $row[1];
}
}
foreach ($newData as $key => $arr) {
fputcsv($file, array($key, $arr['qty'], $arr['price']), ',', '"');
}
fclose($file);
?>
To start with, there's a nice function on the PHP page str_getcsv which will help you end up with a more legible array to work with:
function csv_to_array($filename='', $delimiter=',') {
if(!file_exists($filename) || !is_readable($filename))
return FALSE;
$header = NULL;
$data = array();
if (($handle = fopen($filename, 'r')) !== FALSE) {
while (($row = fgetcsv($handle, 1000, $delimiter)) !== FALSE) {
if(!$header)
$header = $row;
else
$data[] = array_combine($header, $row);
}
fclose($handle);
}
return $data;
}
This is purely for legibility sake but now comes the code which would allow you to work over the array.
$aryInput = csv_to_array('file.csv', ',');
$aryTemp = array();
foreach($aryInput as $aryRow) {
if(isset($aryTemp[$aryRow['code'])) {
$aryTemp[$aryRow['code']['qty'] += $aryRow['qty'];
} else {
$aryTemp[$aryRow['code']] = $aryRow;
}
}
In the above code, it simply:
Loops through the input
Checks whether the key exists in a temporary array
If it does, it just adds the new quantity
If it doesn't, it adds the entire row
Now you can write out your expectant csv file :)

CSV to Json with header row as key

I would like to convert a CSV to Json, use the header row as a key, and each line as object. How do I go about doing this?
----------------------------------CSV---------------------------------
InvKey,DocNum,CardCode
11704,1611704,BENV1072
11703,1611703,BENV1073
---------------------------------PHP-----------------------------------
if (($handle = fopen('upload/BEN-new.csv'. '', "r")) !== FALSE) {
while (($row_array = fgetcsv($handle, 1024, ","))) {
while ($val != '') {
foreach ($row_array as $key => $val) {
$row_array[] = $val;
}
}
$complete[] = $row_array;
}
fclose($handle);
}
echo json_encode($complete);
Just read the first line separately and merge it into every row:
if (($handle = fopen('upload/BEN-new.csv', 'r')) === false) {
die('Error opening file');
}
$headers = fgetcsv($handle, 1024, ',');
$complete = array();
while ($row = fgetcsv($handle, 1024, ',')) {
$complete[] = array_combine($headers, $row);
}
fclose($handle);
echo json_encode($complete);
I find myself converting csv strings to arrays or objects every few months.
I created a class because I'm lazy and dont like copy/pasting code.
This class will convert a csv string to custom class objects:
Convert csv string to arrays or objects in PHP
$feed="https://gist.githubusercontent.com/devfaysal/9143ca22afcbf252d521f5bf2bdc6194/raw/ec46f6c2017325345e7df2483d8829231049bce8/data.csv";
//Read the csv and return as array
$data = array_map('str_getcsv', file($feed));
//Get the first raw as the key
$keys = array_shift($data);
//Add label to each value
$newArray = array_map(function($values) use ($keys){
return array_combine($keys, $values);
}, $data);
// Print it out as JSON
header('Content-Type: application/json');
echo json_encode($newArray);
Main gist:
https://gist.github.com/devfaysal/9143ca22afcbf252d521f5bf2bdc6194
For those who'd like things spelled out a little more + some room to further parse any row / column without additional loops:
function csv_to_json_byheader($filename){
$json = array();
if (($handle = fopen($filename, "r")) !== FALSE) {
$rownum = 0;
$header = array();
while (($row = fgetcsv($handle, 1024, ",")) !== FALSE) {
if ($rownum === 0) {
for($i=0; $i < count($row); $i++){
// maybe you want to strip special characters or merge duplicate columns here?
$header[$i] = trim($row[$i]);
}
} else {
if (count($row) === count($header)) {
$rowJson = array();
foreach($header as $i=>$head) {
// maybe handle special row/cell parsing here, per column header
$rowJson[$head] = $row[$i];
}
array_push($json, $rowJson);
}
}
$rownum++;
}
fclose($handle);
}
return $json;
}

How can I parse a CSV into array with first value as key?

So I have a CSV file that looks like this:
12345, Here is some text
20394, Here is some more text
How can I insert this into an array that looks like so
$text = "12345" => "Here is some text",
"20394" => "Here is some more text";
This is what I currently had to get a single numerical based value on a one tier CSV
if ($handle = fopen("$qid", "r")) {
$csvData = file_get_contents($qid);
$csvDelim = "\r";
$qid = array();
$qid = str_getcsv($csvData, $csvDelim);
} else {
die("Could not open CSV file.");
}
Thanks for the replies, but I still see a potential issue. With these solutions, wouldn't the values store in this way:
$array[0] = 12345
$array[1] = Here is some text 20394
$array[2] = Here is some more text
If I tried this on the example csv above, how would the array be structured?
You can use fgetcsv() to read a line from a file into an array. So something like this:
$a = array();
$f = fopen(....);
while ($line = fgetcsv($f))
{
$key = array_shift($line);
$a[$key] = $line;
}
fclose($f);
var_dump($a);
Assuming that the first row in the CSV file contains the column headers, this will create an associative array using those headers for each row's data:
$filepath = "./test.csv";
$file = fopen($filepath, "r") or die("Error opening file");
$i = 0;
while(($line = fgetcsv($file)) !== FALSE) {
if($i == 0) {
$c = 0;
foreach($line as $col) {
$cols[$c] = $col;
$c++;
}
} else if($i > 0) {
$c = 0;
foreach($line as $col) {
$data[$i][$cols[$c]] = $col;
$c++;
}
}
$i++;
}
print_r($data);
If you are reading a file I can recommend using something like fgetcsv()
This will read each line in the CSV into an array containing all the columns as values.
http://at2.php.net/fgetcsv
$csv_lines = explode('\n',$csv_text);
foreach($csv_lines as $line) {
$csv_array[] = explode(',',$line,1);
}
edit - based on code posted after original question:
if ($handle = fopen("$qid", "r")) {
$csvData = file_get_contents($qid);
$csvDelim = "\r"; // assume this is the line delim?
$csv_lines = explode($csvDelim,$csvData);
foreach($csv_lines as $line) {
$qid[] = explode(',',$line,1);
}
} else {
die("Could not open CSV file.");
}
With your new file with two columns, $qid should become an array with two values for each line.
$csvDelim = ",";
$qid = str_getcsv($csvData, $csvDelim);
$text[$qid[0]] = $qid[1];

Categories