Reputation: 1611
Can someone kindly provide a code to create an array from a CSV file using fgetcsv?
I've used the following code to create an array from a simple CSV file, but it doesn't work right when one of my fields has multiple commas - such as addresses.
$lines =file('CSV Address.csv');
foreach($lines as $data)
{
list($name[],$address[],$status[])
= explode(',',$data);
}
*Also, str_getcsv is not supported by my hosting service.
The above code doesn't work with the following CSV file example. First column is name, second column is address, third column is marital status.
Scott L. Aranda,"123 Main Street, Bethesda, Maryland 20816",Single
Todd D. Smith,"987 Elm Street, Alexandria, Virginia 22301",Single
Edward M. Grass,"123 Main Street, Bethesda, Maryland 20816",Married
Aaron G. Frantz,"987 Elm Street, Alexandria, Virginia 22301",Married
Ryan V. Turner,"123 Main Street, Bethesda, Maryland 20816",Single
Upvotes: 152
Views: 393541
Reputation: 1164
Its my written and solution, of course it doesn't work with the
fgetcsv` function, instead will work for all separated values strings more flexible and concidering to the new lines in the fields too...
function ConvertFromSeparatedValuesFile($path, $delimiter = ',', $enclosure = '"', $eol = "\n") :null|array {
if (file_exists($path) && is_readable($path)){
return ConvertToCells(file_get_contents($path), $delimiter, $enclosure, $eol);
}
return null;
}
function ConvertToCells($svString, $delimiter = ',', $enclosure = '"', $eol = "\n") :array {
if(empty($svString)) return [];
$rows = [];
$length = strlen($svString);
$index = 0;
while ($index < $length) {
$row = [];
$column = '';
$inEnclosure = false;
do {
$char = $svString[$index++];
if ($inEnclosure) {
if ($char == $enclosure) {
if ($index < $length) {
$char = $svString[$index];
if ($char == $enclosure) {
$column .= $char;
$index++;
} else { $inEnclosure = false; }
} else {
$inEnclosure = false;
$row[] = $column;
break;
}
} else { $column .= $char; }
} else if ($char == $enclosure) {
if($index < $length) {
$char = $svString[$index++];
if ($char == $enclosure) { $column .= $char; }
else {
$inEnclosure = true;
$column .= $char;
}
} else {
$row[] = $column;
break;
}
} else if ($char == $delimiter) {
$row[] = $column;
$column = '';
} else if ($char == "\r") {
if ($index < $length) {
$char = $svString[$index];
if ($char == $eol) { $index++; }
}
$row[] = $column;
break;
} else if ($char == $eol) {
$row[] = $column;
break;
} else { $column .= $char; }
if ($index == $length) {
$row[] = $column;
break;
}
} while ($index < $length);
$rows[] = $row;
}
return $rows;
}
Just you sould call the function:
ConvertFromSeparatedValuesFile($path);
Enjoy...
Upvotes: 0
Reputation: 1868
Here is an option to extract values from a CSV file (with any delimiter) into an array of dimension (n_lines, n_fields)
// A function to extract values from a CSV line (with ';' delimiter). Ex: "Song;Artist;Year" --> ["Song","Artist","Year"]
$csv_line_reader = function($line) { return str_getcsv($line, ";"); };
// Read a CSV file and store its content in a array $lines of dim=(n_lines, n_fields=3(Song,Artist,Year))
$lines = array_map($csv_line_reader,
file("path/to/csv_file.csv", FILE_IGNORE_NEW_LINES));
// Do your processing, ie:
foreach ($lines as $line) {
foreach ($line as $field) {
//...
}
Note: Using FILE_IGNORE_NEW_LINES
option avoids creating empty cells when a new line is encountered
Upvotes: 1
Reputation: 606
I've made an utility in PHP that converts CSV data from a file or string to an array of objects, and also offers an option to group the items by an specific column, and you can also change the delimiter from comma to any character you want.
Example:
Brand, Model, Year
Volkswagen, Gol,2008
Fiat, Uno, 2007
Fiat, Palio, 2002
Fiat, Mobi, 2021
Volkswagen, Jetta, 2018
Hyunday, HB20, 2020
Returns: Array made out of CSV
Group by examples:
Grouping by the 'Brand' column
You can find the code here: https://github.com/raphah96/PHPCSV
I deal a lot with CSV so that's why I had to made a consistent utility instead of a simple one time use code.
Upvotes: 0
Reputation: 9
convertToArray(file_get_content($filename));
function convertToArray(string $content): array
{
$data = str_getcsv($content,"\n");
array_walk($data, function(&$a) use ($data) {
$a = str_getcsv($a);
});
return $data;
}
Upvotes: 0
Reputation: 31
function csvToArray($path)
{
try{
$csv = fopen($path, 'r');
$rows = [];
$header = [];
$index = 0;
while (($line = fgetcsv($csv)) !== FALSE) {
if ($index == 0) {
$header = $line;
$index = 1;
} else {
$row = [];
for ($i = 0; $i < count($header); $i++) {
$row[$header[$i]] = $line[$i];
}
array_push($rows, $row);
}
}
return $rows;
}catch (Exception $exception){
return false;
}
}
Upvotes: 3
Reputation: 6125
I have created a function which will convert a csv string to an array. The function knows how to escape special characters, and it works with or without enclosure chars.
$dataArray = csvstring_to_array( file_get_contents('Address.csv'));
I tried it with your csv sample and it works as expected!
function csvstring_to_array($string, $separatorChar = ',', $enclosureChar = '"', $newlineChar = "\n") {
// @author: Klemen Nagode
$array = array();
$size = strlen($string);
$columnIndex = 0;
$rowIndex = 0;
$fieldValue="";
$isEnclosured = false;
for($i=0; $i<$size;$i++) {
$char = $string{$i};
$addChar = "";
if($isEnclosured) {
if($char==$enclosureChar) {
if($i+1<$size && $string{$i+1}==$enclosureChar){
// escaped char
$addChar=$char;
$i++; // dont check next char
}else{
$isEnclosured = false;
}
}else {
$addChar=$char;
}
}else {
if($char==$enclosureChar) {
$isEnclosured = true;
}else {
if($char==$separatorChar) {
$array[$rowIndex][$columnIndex] = $fieldValue;
$fieldValue="";
$columnIndex++;
}elseif($char==$newlineChar) {
echo $char;
$array[$rowIndex][$columnIndex] = $fieldValue;
$fieldValue="";
$columnIndex=0;
$rowIndex++;
}else {
$addChar=$char;
}
}
}
if($addChar!=""){
$fieldValue.=$addChar;
}
}
if($fieldValue) { // save last field
$array[$rowIndex][$columnIndex] = $fieldValue;
}
return $array;
}
Upvotes: 29
Reputation: 31
If you want each line to be in an array, and each cell in the line in array:
$file = fopen('csvFile.csv', 'r'); // Open the file
while (($line = fgetcsv($file)) !== FALSE) { // Read one line
$array[] =$line; // Add the line in the main array
}
echo '<pre>';
print_r($array); //print it out
echo '</pre>';
fclose($file);
Upvotes: 3
Reputation: 324
I came up with this pretty basic code. I think it could be useful to anyone.
$link = "link to the CSV here"
$fp = fopen($link, 'r');
while(($line = fgetcsv($fp)) !== FALSE) {
foreach($line as $key => $value) {
echo $key . " - " . $value . "<br>";
}
}
fclose($fp);
Upvotes: 0
Reputation: 424
To get an array with the right keys, you can try this:
// Open file
$file = fopen($file_path, 'r');
// Headers
$headers = fgetcsv($file);
// Rows
$data = [];
while (($row = fgetcsv($file)) !== false)
{
$item = [];
foreach ($row as $key => $value)
$item[$headers[$key]] = $value ?: null;
$data[] = $item;
}
// Close file
fclose($file);
Upvotes: 6
Reputation: 2989
Try this code:
function readCsv($file)
{
if (($handle = fopen($file, 'r')) !== FALSE) {
while (($lineArray = fgetcsv($handle, 4000)) !== FALSE) {
print_r(lineArray);
}
fclose($handle);
}
}
Upvotes: -1
Reputation: 5444
Try this..
function getdata($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 = 'test.csv';
$csv = getdata($csvFile);
echo '<pre>';
print_r($csv);
echo '</pre>';
Array
(
[0] => Array
(
[0] => Project
[1] => Date
[2] => User
[3] => Activity
[4] => Issue
[5] => Comment
[6] => Hours
)
[1] => Array
(
[0] => test
[1] => 04/30/2015
[2] => test
[3] => test
[4] => test
[5] =>
[6] => 6.00
));
Upvotes: 5
Reputation: 6401
Old question, but still relevant for PHP 5.2 users. str_getcsv is available from PHP 5.3. I've written a small function that works with fgetcsv itself.
Below is my function from https://gist.github.com/4152628:
function parse_csv_file($csvfile) {
$csv = Array();
$rowcount = 0;
if (($handle = fopen($csvfile, "r")) !== FALSE) {
$max_line_length = defined('MAX_LINE_LENGTH') ? MAX_LINE_LENGTH : 10000;
$header = fgetcsv($handle, $max_line_length);
$header_colcount = count($header);
while (($row = fgetcsv($handle, $max_line_length)) !== FALSE) {
$row_colcount = count($row);
if ($row_colcount == $header_colcount) {
$entry = array_combine($header, $row);
$csv[] = $entry;
}
else {
error_log("csvreader: Invalid number of columns at line " . ($rowcount + 2) . " (row " . ($rowcount + 1) . "). Expected=$header_colcount Got=$row_colcount");
return null;
}
$rowcount++;
}
//echo "Totally $rowcount rows found\n";
fclose($handle);
}
else {
error_log("csvreader: Could not read CSV \"$csvfile\"");
return null;
}
return $csv;
}
Returns
Begin Reading CSV
Array
(
[0] => Array
(
[vid] =>
[agency] =>
[division] => Division
[country] =>
[station] => Duty Station
[unit] => Unit / Department
[grade] =>
[funding] => Fund Code
[number] => Country Office Position Number
[wnumber] => Wings Position Number
[title] => Position Title
[tor] => Tor Text
[tor_file] =>
[status] =>
[datetime] => Entry on Wings
[laction] =>
[supervisor] => Supervisor Index Number
[asupervisor] => Alternative Supervisor Index
[author] =>
[category] =>
[parent] => Reporting to Which Position Number
[vacant] => Status (Vacant / Filled)
[index] => Index Number
)
[1] => Array
(
[vid] =>
[agency] => WFP
[division] => KEN Kenya, The Republic Of
[country] =>
[station] => Nairobi
[unit] => Human Resources Officer P4
[grade] => P-4
[funding] => 5000001
[number] => 22018154
[wnumber] =>
[title] => Human Resources Officer P4
[tor] =>
[tor_file] =>
[status] =>
[datetime] =>
[laction] =>
[supervisor] =>
[asupervisor] =>
[author] =>
[category] => Professional
[parent] =>
[vacant] =>
[index] => xxxxx
)
)
Upvotes: 22
Reputation: 92
This function will return array with Header values as array keys.
function csv_to_array($file_name) {
$data = $header = array();
$i = 0;
$file = fopen($file_name, 'r');
while (($line = fgetcsv($file)) !== FALSE) {
if( $i==0 ) {
$header = $line;
} else {
$data[] = $line;
}
$i++;
}
fclose($file);
foreach ($data as $key => $_value) {
$new_item = array();
foreach ($_value as $key => $value) {
$new_item[ $header[$key] ] =$value;
}
$_data[] = $new_item;
}
return $_data;
}
Upvotes: 4
Reputation: 809
Please fin below a link to the function from @knagode, enhanced with a skip rows parameter. https://gist.github.com/gabrieljenik/47fc38ae47d99868d5b3#file-csv_to_array
<?php
/**
* Convert a CSV string into an array.
*
* @param $string
* @param $separatorChar
* @param $enclosureChar
* @param $newlineChar
* @param $skip_rows
* @return array
*/
public static function csvstring_to_array($string, $skip_rows = 0, $separatorChar = ';', $enclosureChar = '"', $newlineChar = "\n") {
// @author: Klemen Nagode
// @source: http://stackoverflow.com/questions/1269562/how-to-create-an-array-from-a-csv-file-using-php-and-the-fgetcsv-function
$array = array();
$size = strlen($string);
$columnIndex = 0;
$rowIndex = 0;
$fieldValue="";
$isEnclosured = false;
for($i=0; $i<$size;$i++) {
$char = $string{$i};
$addChar = "";
if($isEnclosured) {
if($char==$enclosureChar) {
if($i+1<$size && $string{$i+1}==$enclosureChar){
// escaped char
$addChar=$char;
$i++; // dont check next char
}else{
$isEnclosured = false;
}
}else {
$addChar=$char;
}
}else {
if($char==$enclosureChar) {
$isEnclosured = true;
}else {
if($char==$separatorChar) {
$array[$rowIndex][$columnIndex] = $fieldValue;
$fieldValue="";
$columnIndex++;
}elseif($char==$newlineChar) {
echo $char;
$array[$rowIndex][$columnIndex] = $fieldValue;
$fieldValue="";
$columnIndex=0;
$rowIndex++;
}else {
$addChar=$char;
}
}
}
if($addChar!=""){
$fieldValue.=$addChar;
}
}
if($fieldValue) { // save last field
$array[$rowIndex][$columnIndex] = $fieldValue;
}
/**
* Skip rows.
* Returning empty array if being told to skip all rows in the array.
*/
if ($skip_rows > 0) {
if (count($array) == $skip_rows)
$array = array();
elseif (count($array) > $skip_rows)
$array = array_slice($array, $skip_rows);
}
return $array;
}
Upvotes: 1
Reputation: 331
$arrayFromCSV = array_map('str_getcsv', file('/path/to/file.csv'));
Upvotes: 33
Reputation: 243146
Like you said in your title, fgetcsv is the way to go. It's pretty darn easy to use.
$file = fopen('myCSVFile.csv', 'r');
while (($line = fgetcsv($file)) !== FALSE) {
//$line is an array of the csv elements
print_r($line);
}
fclose($file);
You'll want to put more error checking in there in case fopen()
fails, but this works to read a CSV file line by line and parse the line into an array.
Upvotes: 232
Reputation: 154513
I think the str_getcsv() syntax is much cleaner, it also doesn't require the CSV to be stored in the file system.
$csv = str_getcsv(file_get_contents('myCSVFile.csv'));
echo '<pre>';
print_r($csv);
echo '</pre>';
Or for a line by line solution:
$csv = array();
$lines = file('myCSVFile.csv', FILE_IGNORE_NEW_LINES);
foreach ($lines as $key => $value)
{
$csv[$key] = str_getcsv($value);
}
echo '<pre>';
print_r($csv);
echo '</pre>';
Or for a line by line solution with no str_getcsv():
$csv = array();
$file = fopen('myCSVFile.csv', 'r');
while (($result = fgetcsv($file)) !== false)
{
$csv[] = $result;
}
fclose($file);
echo '<pre>';
print_r($csv);
echo '</pre>';
Upvotes: 81