CSV to Array PHP - php

I know there are a lot of resources out there for putting a CSV into an associative array, but I can't find anything that helps a noob like me do exactly what I want to do.
I currently have an associative array defined inside my PHP file:
$users = array(
'v4f25' => 'Stan Parker',
'ntl35' => 'John Smith',
);
I would like to move that array into a CSV file (users.txt) so:
v4f25, Stan Parker
ntl35, John Smith
The next step is to import users.txt so I can use it precisely like I was using the array $users.
Any help here? The last code I tried returned this: (which is not what I want)
array(2) {
["v4f25"]=>
string(5) "ntl35"
["Stan Parker"]=>
string(10) "John Smith"
}

What about the following?
$data = array();
if ($fp = fopen('csvfile.csv', 'r')) {
while (!feof($fp)) {
$row = fgetcsv($fp);
$data[$row[0]] = $row[1];
}
fclose($fp);
}

$users = array(
'v4f25' => 'Stan Parker',
'ntl35' => 'John Smith',
);
$fp = fopen('users.txt', 'w');
if ($fp) {
foreach ($users as $key => $value) {
fputcsv($fp, array($key, $value));
}
fclose($fp);
} else {
exit('Could not open CSV file')
}
See: fputcsv()
UPDATE - in the comments you're interested in how to read the file and get your users back out. Here's the return trip:
$users = array();
if (($handle = fopen("my-csv-file.csv", "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
$users[$data[0]] = $data[1];
}
fclose($handle);
} else {
exit('Could not open CSV file');
}
if (count($users) == 0) {
exit('CSV file empty: no users found');
}

Here's a solution using fputcsv() which flattens the key/value pairs to an array before writing to disk.
$filehandle = fopen("csvfile.csv", "w");
if ($filehandle) {
foreach ($users as $key => $value) {
fputcsv($filehandle, array($key, $value);
}
fclose($filehandle);
}
else // couldn't open file

Try this (assuming your strings contain no commas):
$users = array(
'v4f25' => 'Stan Parker',
'ntl35' => 'John Smith',
);
foreach ($users as $k => $v) {
print "$k, $v\n";
}
Obviously you could then create the CSV file like so:
php above_script.php > outfile.csv
Now, to get from CSV back into an array you could use something like:
$file = 'outfile.csv';
$arr = array();
if (file_exists($file)) {
foreach (explode("\n", file_get_contents($file)) as $l) {
list($k, $v) = explode(',', $l);
$arr[trim($k)] = trim($l);
}
}
print_r($arr, true);
NOTES:
If your strings do (or might) contain commas, then you'll probably want to use a PHP builtin function to decode them - in which case the answers by harald and artlung are useful.
RFC 4180 describes how commas (and other values) are encoded in CSV, in case you want to roll your own CSV encoding/decoding functions for whatever reason.

Related

PHP: Expects parameter to be string array given

I am trying to read a csv file line by line and save its content in an array. I then parse the array using foreach to print each line.
However, when i try to send the variable(which according to me should be a string) to the deleteInstance method it prints as an array and not plain string.
I have issue sending this to Softlayer API since it throw me an error saying string expected but array given ? I am not sure what is wrong
a.csv
7381838
7381840
7381842
php
<?PHP
require_once dirname(__FILE__) . '/SoftLayer/SoapClient.class.php';
function readCSV($csvFile){
$file_handle = fopen($csvFile, 'r');
while (!feof($file_handle) ) {
$line_of_text[] = fgetcsv($file_handle, 1024);
}
fclose($file_handle);
return $line_of_text;
}
// Set path to CSV file
$csvFile = 'a.csv';
$csv = readCSV($csvFile);
foreach ($csv as $value) {
var_dump($value);
print_r($value);
deleteInstance($value);
}
function deleteInstance($ccid){
$apiUsername = 'xxxxx';
$apiKey = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
$cancelRightNow = true; //or false if you want to wait till the billing cycle ends
$cloudComputingInstanceId = $ccid;
print_r($cloudComputingInstanceId);
var_dump($cloudComputingInstanceId);
$client = SoftLayer_SoapClient::getClient('SoftLayer_Virtual_Guest', $cloudComputingInstanceId, $apiUsername, $apiKey);
$objectMask = new SoftLayer_ObjectMask();
$objectMask->billingItem;
$client->setObjectMask($objectMask);
$cci = $client->getObject();
$client = SoftLayer_SoapClient::getClient('SoftLayer_Billing_Item', $cci->billingItem->id, $apiUsername, $apiKey);
$billingItem = $client->getObject();
if ($billingItem != null) {
if ($cancelRightNow) {
$client->cancelService();
} else {
$client->cancelServiceOnAnniversaryDate();
}
}
}
?>
The problem is your argument to deleteInstance is an array... It looks like this:
$csv = Array(
0 => Array(0 => '7381838'),
1 => Array (0 => '7381840'),
2 => Array(0 => '7381842')
)
This is because you are parsing it as CSV which splits each line into an array based on a delimiter. This is not what you want. Instead use file to read each line into an array:
function readCSV($csvFile){
return file($csvFile);
}
$csv = readCSV('a.csv');
foreach ($csv as $value) {
// your value is now the line of the file like '7381838'
deleteInstance($value);
}
Try this and see what happens
foreach ($csv as $value) {
$svalue = $value[0];
var_dump($svalue);
print_r($svalue);
deleteInstance($svalue);
}

Prevent array overwriting and instead create new array index

I have a file and I need the save the content of the file in my MySQL database. Here is the code that I am using to parse the file:
$lines = file($tmp_filename);
$data = array();
if (($handle = fopen($tmp_filename, 'r')) !== FALSE)
{
while (($row = fgetcsv($handle, 1000, ";", "\"", "\n")) !== FALSE)
{
$key = array_shift($row);
$data[$key] = $row;
}
fclose($handle);
}
and here are the contents of the file that I am parsing:
HDR;Payroll Interface;5496;2012-07-20
NM1;082;IN2;12345678;2001-01-15;Mr;Marcial;Gustav;Gustav,Marcial;PRI;Marcial
PR1;082;IN2;12345678;7 The School;Alvarez;Bahaghari; ;Gandum
PR2;082;IN2;12345678;400006;IND;M;M;2007-10-16;1976-03-31
PR3;082;IN2;12345678; ; ;A;
**truncated**
Click Here for full data
There are scenarios where the array has the same index and the same value but I still need to save these data but array overwriting occurs. What must be added to put the same array to a different array index?
Take a look at this and tell me what i am missing
The data in the array is being overwritten because you are reassigning the value of $key each time it is encountered.
What you want to do is create a secondary array as the $key value and push nodes into that array this way you end up with your expected result.
[
'NM1' => ['...', '...'],
'PR1' => ['...', '...']
]
The code would be,
while (($row = fgetcsv($handle, 1000, ";", "\"", "\n")) !== FALSE) {
$key = array_shift($row);
// Notice the extra []
$data[$key][] = $row;
}
Each key will now contain an array with a node for each row encountered.
try changing:
...
$data[$key] = $row;
to
...
$data[][$key] = $row;

PHP get string from CSV for a duplicate entry

I have this big file containing SWIFT numbers and bank names. I'm using the following php function for reading and comparing data:
function csv_query($blz) {
$cdata = -1;
$fp = fopen(DIR_WS_INCLUDES . 'data/swift.csv', 'r');
while ($data = fgetcsv($fp, 1024, ",")) {
if ($data[0] == $blz){
$cdata = array ('blz' => $data[0],
'bankname' => $data[7]);
// 'prz' => $data[2]
}
}
return $cdata;
}
The csv files looks like that:
"20730054",1,"UniCredit Bank - HypoVereinsbank (ex VereinWest)","21423","Winsen (Luhe)","UniCredit Bk ex VereinWest",,"HYVEDEMM324","68","013765","M",1,"20030000"
"20750000",1,"Sparkasse Harburg-Buxtehude","21045","Hamburg","Spk Harburg-Buxtehude","52002","NOLADE21HAM","00","011993","U",0,"00000000"
"20750000",2,"Sparkasse Harburg-Buxtehude","21605","Buxtehude","Spk Harburg-Buxtehude","52002",,"00","011242","U",0,"00000000"
As you can see from the code, I need the first and the eight string. If the first string has no duplicates everything is ok, but if it has, most likely the eighth field of the duplicate will be empty and I get no result back. So I want to ask how to display that eighth field of the first result if the line has a duplicate.
I guess this will solve your problem :
function csv_query($blz) {
$cdata = -1;
$fp = fopen(DIR_WS_INCLUDES . 'data/swift.csv', 'r');
$counter = 0; // add this line
while ($data = fgetcsv($fp, 1024, ",")) {
if ($data[0] == $blz && !$counter) { //change this line
$cdata = array(
'blz' => $data[0],
'bankname' => $data[7]
);
$counter++; //add this line
}
}
return $cdata;
}

CSV to Associative Array

I've seen numerous examples on how to take a CSV file and then create an associative array with the headers as the keys.
For example:
Brand,Model,Part,Test
Honda,Civic,123,244
Honda,Civic,135,434
Toyota,Supra,511,664
Where it would create an Array such as Array[$num][$key] where $key would be Brand, Model, Part, Test.
So If I wanted to access the test value "434" I would have to loop every index in the array and then ignore any Brands that were not honda, and any models that were not Civic
What I need to do is access the value most directly, instead of running through a for loop going through each $num index. I want to be able to access the value test "434" with:
Array['Honda']['Civic']['135']
or control a for statement with looping through every model Honda has... something like
foreach $model in Array['Honda']
At the very least I need to be able to go through every model given a known Brand and access all the relative info for each.
Edit:
Just to confirm I was setting this up an example. My actually data has headers like:
brand model part price shipping description footnote
Of which I need to access all the information tied to the part (price, shipping,desc, footnote)
Too many long solutions. I've always found this to be the simplest:
<?php
/* Map Rows and Loop Through Them */
$rows = array_map('str_getcsv', file('file.csv'));
$header = array_shift($rows);
$csv = array();
foreach($rows as $row) {
$csv[] = array_combine($header, $row);
}
?>
run over the csv file line by line, and insert to array like:
$array = $fields = array(); $i = 0;
$handle = #fopen("file.csv", "r");
if ($handle) {
while (($row = fgetcsv($handle, 4096)) !== false) {
if (empty($fields)) {
$fields = $row;
continue;
}
foreach ($row as $k=>$value) {
$array[$i][$fields[$k]] = $value;
}
$i++;
}
if (!feof($handle)) {
echo "Error: unexpected fgets() fail\n";
}
fclose($handle);
}
To create an associative list array use something like:
$keys = fgetcsv($f);
while (!feof($f)) {
$array[] = array_combine($keys, fgetcsv($f));
}
And to traverse and filter by specific attributes write a function like:
function find($find) {
foreach ($array as $row) {
if (array_intersect_assoc($row, $find) == $find) {
$result[] = $row;
}
}
}
Where you would invoke it with $find = array(Brand=>Honda, Model=>Civic, Part=>135) to filter out the searched models. The other positional array structure seems not very workable, unless you only want to access the "Test" attribute.
Try this simple algorithm:
$assocData = array();
if( ($handle = fopen( $importedCSVFile, "r")) !== FALSE) {
$rowCounter = 0;
while (($rowData = fgetcsv($handle, 0, ",")) !== FALSE) {
if( 0 === $rowCounter) {
$headerRecord = $rowData;
} else {
foreach( $rowData as $key => $value) {
$assocData[ $rowCounter - 1][ $headerRecord[ $key] ] = $value;
}
}
$rowCounter++;
}
fclose($handle);
}
var_dump( $assocData);
Using fgetcsv() seems the most direct and sensible tool for the job.
csv.csv contents:
Brand,Model,Part,Test
Honda,Civic,123,244
Honda,Civic,135,434
Toyota,Supra,511,664
Code:
$assoc_array = [];
if (($handle = fopen("csv.csv", "r")) !== false) { // open for reading
if (($data = fgetcsv($handle, 1000, ",")) !== false) { // extract header data
$keys = $data; // save as keys
}
while (($data = fgetcsv($handle, 1000, ",")) !== false) { // loop remaining rows of data
$assoc_array[] = array_combine($keys, $data); // push associative subarrays
}
fclose($handle); // close when done
}
echo "<pre>";
var_export($assoc_array); // print to screen
echo "</pre>";
Output:
array (
0 =>
array (
'Brand' => 'Honda',
'Model' => 'Civic',
'Part' => '123',
'Test' => '244',
),
1 =>
array (
'Brand' => 'Honda',
'Model' => 'Civic',
'Part' => '135',
'Test' => '434',
),
2 =>
array (
'Brand' => 'Toyota',
'Model' => 'Supra',
'Part' => '511',
'Test' => '664',
),
)
Resource: http://php.net/manual/en/function.fgetcsv.php
Here is a solutions that will work by specifying a local file or URL. You can also switch the association on and off. Hopefully this helps.
class CSVData{
public $file;
public $data;
public $fp;
public $caption=true;
public function CSVData($file=''){
if ($file!='') getData($file);
}
function getData($file){
if (strpos($file, 'tp://')!==false){
copy ($file, '/tmp/csvdata.csv');
if ($this->fp=fopen('/tmp/csvdata.csv', 'r')!==FALSE){
$this->readCSV();
unlink('tmp/csvdata.csv');
}
} else {
$this->fp=fopen($file, 'r');
$this->readCSV();
}
fclose($this->fp);
}
private function readCSV(){
if ($this->caption==true){
if (($captions=fgetcsv($this->fp, 1000, ","))==false) return false;
}
$row=0;
while (($data = fgetcsv($this->fp, 1000, ",")) !== FALSE) {
for ($c=0; $c < count($data); $c++) {
$this->data[$row][$c]=$data[$c];
if ($this->caption==true){
$this->data[$row][$captions[$c]]=$data[$c];
}
}
$row++;
}
}
}
Try this usage:
$o=new CSVData();
$o->getData('/home/site/datafile.csv');
$data=$o->data;
print_r($data);
Here is my solution, similar to others stated but uses a while loop with fgetcsv, and uses a counter and array_combine to set the first row as the keys.
$rownum = 0;
while (($row = fgetcsv($openedFile, 1000, ',')) !== FALSE) {
if ($rownum > 0) {
$row = array_combine($importarray[0], $row);
}
array_push($importarray, $row);
$rownum++;
}
array_shift($importarray);

How to extract data from csv file in PHP

I have a csv file which looks like this
$lines[0] = "text, with commas", "another text", 123, "text",5;
$lines[1] = "some without commas", "another text", 123, "text";
$lines[2] = "some text with commas or no",, 123, "text";
And I would like to have a table:
$t[0] = array("text, with commas", "another text", "123", "text","5");
$t[1] = array("some without commas", "another text", "123", "text");
$t[2] = array("some text, with comma,s or no", NULL , "123", "text");
If I use split($lines[0],",") I'll get "text" ,"with commas" ...
Is there any elegant way to do it?
You can use fgetcsv to parse a CSV file without having to worry about parsing it yourself.
Example from PHP Manual:
$row = 1;
if (($handle = fopen("test.csv", "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
$num = count($data);
echo "<p> $num fields in line $row: <br /></p>\n";
$row++;
for ($c=0; $c < $num; $c++) {
echo $data[$c] . "<br />\n";
}
}
fclose($handle);
}
In addition to Matt's suggestion, you can also use SplFileObject to read in the file:
$file = new SplFileObject("data.csv");
$file->setFlags(SplFileObject::READ_CSV);
$file->setCsvControl(',', '"', '\\'); // this is the default anyway though
foreach ($file as $row) {
list ($fruit, $quantity) = $row;
// Do something with values
}
source: http://de.php.net/manual/en/splfileobject.setcsvcontrol.php
you can read the data using the following function.
function readCSV() {
$csv = array_map('str_getcsv', file('data.csv'));
array_shift($csv); //remove headers
}
http://www.pearlbells.co.uk/how-to-sort-a1a2-z9z10aa1aa2-az9az10-using-php/
here is also a simple method to get read csv file.
$sfp = fopen('/path/to/source.csv','r');
$dfp = fopen('/path/to/destination.csv','w');
while ($row = fgetcsv($sfp,10000,",","")) {
$goodstuff = "";
$goodstuff = str_replace("¦",",",$row[2]);
$goodstuff .= "\n";
fwrite($dfp,$goodstuff);
}
fclose($sfp);
fclose($dfp);
Maybe my code solves your problem:
// Parse all content from csv file and generate array from line.
function csv_content_parser($content) {
foreach (explode("\n", $content) as $line) {
// Generator saves state and can be resumed when the next value is required.
yield str_getcsv($line);
}
}
// Get content from csv file.
$content = file_get_contents('your_file.csv');
// Create one array from csv file's lines.
$data = array();
foreach (csv_content_parser($content) as $fields) {
array_push($data, $fields);
}
In result you have an array with all values from csv.
It would be something like:
Array
(
[0] => Array
(
[0] => text, with commas
[1] => another text
[2] => 123
[3] => text
[4] => 5
)
[1] => Array
(
[0] => some without commas
[1] => another text
[2] => 123
[3] => text
)
[2] => Array
(
[0] => some text, with comma,s or no
[1] => NULL
[2] => 123
[3] => text
)
)
Suppose you have a create a function for same things, Then it should look like
function csvtoarray($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);
}
if(file_exists($filename)) #unlink($filename);
return $data;
}
$data = csvtoarray('file.csv', ',');
print_r($data);
You could use something like https://github.com/htmlburger/carbon-csv that allows column mapping:
$csv = new \Carbon_CSV\CsvFile('path-to-file/filename.csv');
$csv->set_column_names([
0 => 'first_name',
1 => 'last_name',
2 => 'company_name',
3 => 'address',
]);
foreach ($csv as $row) {
print_r($row);
}
The result of the below code would be something like:
Array
(
[0] => Array
(
[first_name] => John
[last_name] => Doe
[company_name] => Simple Company Name
[address] => Street Name, 1234, City Name, Country Name
)
[1] => Array
(
[first_name] => Jane
[last_name] => Doe
[company_name] => Nice Company Name
[address] => Street Name, 5678, City Name, Country Name
)
)
Another library that does the same thing(and much more) is http://csv.thephpleague.com/9.0/reader/
When you want to keep the index (first line) for multidimensional result array, you can use:
$delim = ';';
$csvFile = file($csv_file);
$firstline = str_getcsv($csvFile[0], $delim);
$data = array();
foreach ($csvFile as $line) {
$line = str_getcsv($line, $delim);
$data[] = array_combine($firstline, $line);
}
I've built an application to extract data from a CSV file , this php application was used to show a daily quote for users.
The full project on github: 365-quotes-php-csv.
Also this is the class Code for the application i've built
<?php
/*
Main Class
please note :
1- the CSV file must be comma separated (,) and each line must End with (;).
2- Feel free to edit the all.CSV file and add all of your 366 New Quotes.
3- don't change any thing specially the CSV file Location.
---------------------------------------------------------------------------
RISS.WORK all copy rights reserved 2018
please Don't Remove
Github/RissWork
Email : info#riss.work
*/
class Quote{
//properties
private $_quote,$_allQuotes;
private static $_instance = null;
//Constructor
private function __construct(){
//Day Count
$dayCount = date(z);
if($this->readCsvAndGetQuote($dayCount)){
return $this->getQuote();
}else{
echo 'Error Cannot open the .CSV File';
}
}
//Methods
//get Instance
public function getInstance(){
if(!isset(self::$_instance)){
self::$_instance = new Quote();
}
return self::$_instance;
}//end of get Instance
//get daily Quote
public function getQuote(){
return $this->_quote;
}//end of get Quote
//Read CSV
private function readCsvAndGetQuote($dayCount = 1 ){
if(($handel = fopen("csv/all.csv" , "r")) !== false){
$this->_allQuotes = fgetcsv($handel,1000000,';');
$this->_quote = explode(',',$this->_allQuotes[$dayCount]);
return true;
}
return false;
}//end of read CSV
}//end of Class
Return a php mapping array with the column of interests :
public function extractCSVDatas($file_uri) {
$AliasToSystemPathMappingArray = [];
if (($handle = fopen($file_uri, "r")) !== FALSE) {
$csv = array_map('str_getcsv', file($file_uri));
//remove header and choose columns among the list:
foreach((array_slice($csv,1)) as $line) {
list($id, $alias, $systemPath) = explode(';',$line[0]);
$AliasToSystemPathMappingArray[] = [$alias, $systemPath];
}
fclose($handle);
}
return $AliasToSystemPathMappingArray;
}
/**
* #return mixed[]
*/
public function csvToArray(string $delimiter, string $filename = ''): array
{
$data = [];
if (file_exists($filename) && is_readable($filename)) {
$header = null;
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;
}
And why must it be simple when it can be complicated?
Joke aside, here is a quick and easy solution using the PHP function str_getcsv()
Here is an example:
function parse_csv( $filename_or_text, $delimiter=',', $enclosure='"', $linebreak="\n" )
{
$return = array();
if(false !== ($csv = (filter_var($filename_or_text, FILTER_VALIDATE_URL) ? file_get_contents($filename_or_text) : $filename_or_text)))
{
$csv = trim($csv);
$csv = mb_convert_encoding($csv, 'UTF-16LE');
foreach(str_getcsv($csv, $linebreak, $enclosure) as $row){
$col = str_getcsv($row, $delimiter, $enclosure);
$col = array_map('trim', $col);
$return[] = $col;
}
}
else
{
throw new \Exception('Can not open the file.');
$return = false;
}
return $return;
}
Imagine a situation where you need a function that works with both URL and comma delimited text. This is exactly the function that works like that. Just simply insert a CSV URL or comma separated text and it work nicely.
Just created a function that extracts data from .csv file or csv formatted text and then parses it for more convenient usage (presuming the first line is the columns). Works with however many rows/columns you'd like/have, just simply point the function to the file location/string and it will return the results!
function csvParse($input, $callback = false){
$results = [];
$raw_array = (is_file($input)) ? array_map('str_getcsv', file($input)) : array_map('str_getcsv', explode("\n", $input));
$array = array_splice($raw_array, 1, count($raw_array));
foreach($raw_array[0] as $c) $columns[] = $c;
foreach($array as $key0 => $val0)
foreach($val0 as $key1 => $val1)
$results[$key0][$columns[$key1]] = $val1;
if(is_callable($callback)) call_user_func_array($callback, array($results));
else return $results;
}
# Either One Would Work
$input = "dir/file.csv";
$input = "name,age,occupation,city\nCrimin4L,24,Programmer,New York\nMrAwesome,20,Gamer,Los Angeles";
# Usage #1
$array = csvParse($input);
var_export($array);
# Usage #2
csvParse($input, function($array){
var_export($array);
});
Input:
name,age,occupation,city
Crimin4L,24,Programmer,New York
MrAwesome,20,Gamer,Los Angeles
Array Output:
array (
0 =>
array (
'name' => 'Crimin4L',
'age' => '24',
'occupation' => 'programmer',
'city' => 'New York',
),
1 =>
array (
'name' => 'MrAwesome',
'age' => '20',
'occupation' => 'gamer',
'city' => 'Los Angeles',
),
)
Live Demo: https://ideone.com/Sa1aMO

Categories