str_getcsv

(No version information available, might be only in CVS)

str_getcsv — Parse a CSV string into an array

Описание

array str_getcsv ( string $input [, string $delimiter [, string $enclosure [, string $escape ]]] )

Внимание

К настоящему времени эта функция еще не была документирована; для ознакомления доступен только список аргументов.

Смотрите также

Коментарии

Автор:
RFC 4180 which deals with CSVs states the escape character is supposed to be a double quotation mark: (page 2)
   7.  If double-quotes are used to enclose fields, then a double-quote
       appearing inside a field must be escaped by preceding it with
       another double quote.  For example:

       "aaa","b""bb","ccc"
2008-05-05 16:15:14
http://php5.kiev.ua/manual/ru/function.str-getcsv.html
For those who need this function but not yet installed in their environment, you can use my function bellow.

You can parse your csv file into an associative array (by default) for each lines, or into an object.
<?php
function parse_csv($file$options null) {
   
$delimiter = empty($options['delimiter']) ? "," $options['delimiter'];
   
$to_object = empty($options['to_object']) ? false true;
   
$str file_get_contents($file);
   
$lines explode("\n"$str);
   
pr($lines);
   
$field_names explode($delimiterarray_shift($lines));
    foreach (
$lines as $line) {
       
// Skip the empty line
       
if (empty($line)) continue;
       
$fields explode($delimiter$line);
       
$_res $to_object ? new stdClass : array();
        foreach (
$field_names as $key => $f) {
            if (
$to_object) {
               
$_res->{$f} = $fields[$key];
            } else {
               
$_res[$f] = $fields[$key];
            }
        }
       
$res[] = $_res;
    }
    return 
$res;
}
?>

NOTE:
Line number 1 of the csv file will be considered as header (field names).

TODO:
- Enclosure handling
- Escape character handling
- Other features/enhancements as you need

EXAMPLE USE:
Content of /path/to/file.csv:
CODE,COUNTRY
AD,Andorra
AE,United Arab Emirates
AF,Afghanistan
AG,Antigua and Barbuda

<?php
$arr_csv 
parse_csv("/path/to/file.csv");
print_r($arr_csv);
?>
// Output:
Array
(
    [0] => Array
        (
            [CODE] => AD
            [COUNTRY] => Andorra
        )
    [1] => Array
        (
            [CODE] => AE
            [COUNTRY] => United Arab Emirates
        )
    [2] => Array
        (
            [CODE] => AF
            [COUNTRY] => Afghanistan
        )
    [3] => Array
        (
            [CODE] => AG
            [COUNTRY] => Antigua and Barbuda
        )
)

<?php
$obj_csv 
parse_csv("/path/to/file.csv", array("to_object" => true));
print_r($obj_csv);
?>
// Output:
Array
(
    [0] => stdClass Object
        (
            [CODE] => AD
            [COUNTRY] => Andorra     
        )
    [1] => stdClass Object
        (
            [CODE] => AE
            [COUNTRY] => United Arab Emirates     
        )
    [2] => stdClass Object
        (
            [CODE] => AF
            [COUNTRY] => Afghanistan     
        )
    [3] => stdClass Object
        (
            [CODE] => AG
            [COUNTRY] => Antigua and Barbuda     
        )
    [4] => stdClass Object
        (
            [CODE] => 
            [COUNTRY] => 
        )
)

// If you use character | (pipe) as delimiter in your csv file, use:
<?php
$arr_csv 
parse_csv("/path/to/file.csv", array("delimiter"=>"|"));
?>

==NSD==
2008-09-15 07:29:18
http://php5.kiev.ua/manual/ru/function.str-getcsv.html
If your happy enough having just a multi-dimensional array, this should work fine. I had wanted to use the one provided by keananda but it was choking on pr($lines).

<?php
function f_parse_csv($file$longest$delimiter) {
 
$mdarray = array();
 
$file    fopen($file"r");
  while (
$line fgetcsv($file$longest$delimiter)) {
   
array_push($mdarray$line);
    }
 
fclose($file);
  return 
$mdarray;
  }
?>

$longest is a number that represents the longest line in the csv file as required by fgetcsv().  The page for fgetcsv() said that the longest line could be set to 0 or left out, but I couldn't get it to work without. I just made it extra large when I had to use it.
2008-09-18 06:19:26
http://php5.kiev.ua/manual/ru/function.str-getcsv.html
Don't have this? Ask fgetcsv() to do it for you.

5.1.0+

<?php
if (!function_exists('str_getcsv')) {
    function 
str_getcsv($input$delimiter ","$enclosure '"'$escape "\\") {
       
$fiveMBs 1024 1024;
       
$fp fopen("php://temp/maxmemory:$fiveMBs"'r+');
       
fputs($fp$input);
       
rewind($fp);

       
$data fgetcsv($fp1000$delimiter$enclosure); //  $escape only got added in 5.3.0

       
fclose($fp);
        return 
$data;
    }
}
?>
2009-01-19 18:48:15
http://php5.kiev.ua/manual/ru/function.str-getcsv.html
Автор:
After using several methods in the past to create CSV strings without using files (disk IO sucks), I finally decided it's time to write a function to handle it all. This function could use some cleanup, and the variable type test might be overkill for what is needed, I haven't thought about it too much.

Also, I took the liberty of replacing fields with certain data types with strings which I find much easier to work with. Some of you may not agree with those. Also, please note that the type "double" or float has been coded specifically for two digit precision because if I am using a float, it's most likely for currency.

I am sure some of you out there would appreciate this function.

<?php
   
function str_putcsv($array$delimiter ','$enclosure '"'$terminator "\n") {
       
# First convert associative array to numeric indexed array
       
foreach ($array as $key => $value$workArray[] = $value;

       
$returnString '';                 # Initialize return string
       
$arraySize count($workArray);     # Get size of array
       
       
for ($i=0$i<$arraySize$i++) {
           
# Nested array, process nest item
           
if (is_array($workArray[$i])) {
               
$returnString .= str_putcsv($workArray[$i], $delimiter$enclosure$terminator);
            } else {
                switch (
gettype($workArray[$i])) {
                   
# Manually set some strings
                   
case "NULL":     $_spFormat ''; break;
                    case 
"boolean"$_spFormat = ($workArray[$i] == true) ? 'true''false'; break;
                   
# Make sure sprintf has a good datatype to work with
                   
case "integer"$_spFormat '%i'; break;
                    case 
"double":   $_spFormat '%0.2f'; break;
                    case 
"string":   $_spFormat '%s'; break;
                   
# Unknown or invalid items for a csv - note: the datatype of array is already handled above, assuming the data is nested
                   
case "object":
                    case 
"resource":
                    default:         
$_spFormat ''; break;
                }
                               
$returnString .= sprintf('%2$s'.$_spFormat.'%2$s'$workArray[$i], $enclosure);
$returnString .= ($i < ($arraySize-1)) ? $delimiter $terminator;
            }
        }
       
# Done the workload, return the output information
       
return $returnString;
    }

?>
2009-01-20 19:20:46
http://php5.kiev.ua/manual/ru/function.str-getcsv.html
Drawing inspiration from daniel dot oconnor at gmail dot com, here's an alternative str_putcsv() that leverages existing PHP core functionality (5.1.0+) to avoid re-inventing the wheel.

<?php
if(!function_exists('str_putcsv')) {
    function 
str_putcsv($input$delimiter ','$enclosure '"') {
       
// Open a memory "file" for read/write...
       
$fp fopen('php://temp''r+');
       
// ... write the $input array to the "file" using fputcsv()...
       
fputcsv($fp$input$delimiter$enclosure);
       
// ... rewind the "file" so we can read what we just wrote...
       
rewind($fp);
       
// ... read the entire line into a variable...
       
$data fgets($fp);
       
// ... close the "file"...
       
fclose($fp);
       
// ... and return the $data to the caller, with the trailing newline from fgets() removed.
       
return rtrim$data"\n" );
    }
}
?>
2009-02-06 17:32:20
http://php5.kiev.ua/manual/ru/function.str-getcsv.html
Автор:
For some reason o'connor's code only reads one line of a csv for me... I had to replace the line 

      $data = fgetcsv($fp, 1000, $delimiter, $enclosure); //  $escape only got added in 5.3.0 

with this:

      $data;
      while (!feof($fp))
      {
        $data[] = fgetcsv($fp, 0, $delimiter, $enclosure); //  $escape only got added in 5.3.0
      }

...to get all of the data out of my string (some post data pasted into a textbox and processed only with stripslashes).
2009-03-17 00:02:16
http://php5.kiev.ua/manual/ru/function.str-getcsv.html
Автор:
Here's a little function to convert a multi-line CSV string to an array:

<?php
function csv_to_array($csv$delimiter ','$enclosure '"'$escape '\\'$terminator "\n") {
   
$r = array();
   
$rows explode($terminator,trim($csv));
   
$names array_shift($rows);
   
$names str_getcsv($names,$delimiter,$enclosure,$escape);
   
$nc count($names);
    foreach (
$rows as $row) {
        if (
trim($row)) {
           
$values str_getcsv($row,$delimiter,$enclosure,$escape);
            if (!
$values$values array_fill(0,$nc,null);
           
$r[] = array_combine($names,$values);
        }
    }
    return 
$r;
}
?>
2009-12-14 19:49:06
http://php5.kiev.ua/manual/ru/function.str-getcsv.html
I found myself wanting to parse a CSV and didn't have access to str_getcsv, so I wrote substitute for PHP < 5.3, hope it helps someone out there stuck in the same situation.

<?php
if (!function_exists('str_getcsv')) { 
    function 
str_getcsv($input$delimiter ','$enclosure '"'$escape '\\'$eol '\n') { 
        if (
is_string($input) && !empty($input)) { 
           
$output = array(); 
           
$tmp    preg_split("/".$eol."/",$input); 
            if (
is_array($tmp) && !empty($tmp)) { 
                while (list(
$line_num$line) = each($tmp)) { 
                    if (
preg_match("/".$escape.$enclosure."/",$line)) {
                        while (
$strlen strlen($line)) { 
                           
$pos_delimiter       strpos($line,$delimiter); 
                           
$pos_enclosure_start strpos($line,$enclosure); 
                            if (
                               
is_int($pos_delimiter) && is_int($pos_enclosure_start
                                && (
$pos_enclosure_start $pos_delimiter)
                                ) {
                               
$enclosed_str substr($line,1); 
                               
$pos_enclosure_end strpos($enclosed_str,$enclosure); 
                               
$enclosed_str substr($enclosed_str,0,$pos_enclosure_end); 
                               
$output[$line_num][] = $enclosed_str
                               
$offset $pos_enclosure_end+3
                            } else {
                                if (empty(
$pos_delimiter) && empty($pos_enclosure_start)) {
                                   
$output[$line_num][] = substr($line,0);
                                   
$offset strlen($line);
                                } else {
                                   
$output[$line_num][] = substr($line,0,$pos_delimiter);
                                   
$offset = (
                                                !empty(
$pos_enclosure_start
                                                && (
$pos_enclosure_start $pos_delimiter)
                                                )
                                                ?
$pos_enclosure_start
                                               
:$pos_delimiter+1
                                } 
                            } 
                           
$line substr($line,$offset); 
                        } 
                    } else { 
                       
$line preg_split("/".$delimiter."/",$line);
   
                       
/*
                         * Validating against pesky extra line breaks creating false rows.
                         */
                       
if (is_array($line) && !empty($line[0])) {
                           
$output[$line_num] = $line;
                        } 
                    } 
                } 
                return 
$output
            } else { 
                return 
false
            } 
        } else { 
            return 
false
        } 
    }
}
?>
2010-05-25 12:50:49
http://php5.kiev.ua/manual/ru/function.str-getcsv.html
Автор:
Here is a quick and easy way to convert a CSV file to an associated array:

<?php
/**
 * @link http://gist.github.com/385876
 */
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($handle1000$delimiter)) !== FALSE)
        {
            if(!
$header)
               
$header $row;
            else
               
$data[] = array_combine($header$row);
        }
       
fclose($handle);
    }
    return 
$data;
}

?>
2010-08-10 16:50:05
http://php5.kiev.ua/manual/ru/function.str-getcsv.html
As the str_getcsv(), unlike to fgetcsv(), does not parse the rows in CSV string, I have found following easy workaround:

<?php
$Data 
str_getcsv($CsvString"\n"); //parse the rows
foreach($Data as &$Row$Row str_getcsv($Row";"); //parse the items in rows
?>

Why not use explode() instead of str_getcsv() to parse rows? Because explode() would not treat possible enclosured parts of string or escaped characters correctly.
2011-01-16 13:39:57
http://php5.kiev.ua/manual/ru/function.str-getcsv.html
Note that this function can also be used to parse other types of constructions. For example, I have used to parse .htaccess AddDescription lines:

    AddDescription "My description to the file." filename.jpg

Those lines can be parsed like this:

<?php

$line 
'AddDescription "My description to the file." filename.jpg';

$parsed str_getcsv(
   
$line# Input line
   
' ',   # Delimiter
   
'"',   # Enclosure
   
'\\'   # Escape char
);

var_dump$parsed );

?>

The output:

array(3) {
  [0]=>
  string(14) "AddDescription"
  [1]=>
  string(27) "My description to the file."
  [2]=>
  string(12) "filename.jpg"
}
2011-11-27 06:26:03
http://php5.kiev.ua/manual/ru/function.str-getcsv.html
I've written this to handle :
- fields with or without enclosure;
- escape and enclosure characters using the same character (ie <<">> in Excel) 

<?php
/**
             * Converts a csv file into an array of lines and columns.
             * khelibert@gmail.com
             * @param $fileContent String
             * @param string $escape String
             * @param string $enclosure String
             * @param string $delimiter String
             * @return array
             */
           
function csvToArray($fileContent,$escape '\\'$enclosure '"'$delimiter ';')
            {
               
$lines = array();
               
$fields = array();

                if(
$escape == $enclosure)
                {
                   
$escape '\\';
                   
$fileContent str_replace(array('\\',$enclosure.$enclosure,"\r\n","\r"),
                                array(
'\\\\',$escape.$enclosure,"\\n","\\n"),$fileContent);
                }
                else
                   
$fileContent str_replace(array("\r\n","\r"),array("\\n","\\n"),$fileContent);

               
$nb strlen($fileContent);
               
$field '';
               
$inEnclosure false;
               
$previous '';

                for(
$i 0;$i<$nb$i++)
                {
                   
$c $fileContent[$i];
                    if(
$c === $enclosure)
                    {
                        if(
$previous !== $escape)
                           
$inEnclosure ^= true;
                        else
                           
$field .= $enclosure;
                    }
                    else if(
$c === $escape)
                    {
                       
$next $fileContent[$i+1];
                        if(
$next != $enclosure && $next != $escape)
                           
$field .= $escape;
                    }
                    else if(
$c === $delimiter)
                    {
                        if(
$inEnclosure)
                           
$field .= $delimiter;
                        else
                        {
                           
//end of the field
                           
$fields[] = $field;
                           
$field '';
                        }
                    }
                    else if(
$c === "\n")
                    {
                       
$fields[] = $field;
                       
$field '';
                       
$lines[] = $fields;
                       
$fields = array();
                    }
                    else
                       
$field .= $c;
                   
$previous $c;
                }
               
//we add the last element
               
if(true || $field !== '')
                {
                   
$fields[] = $field;
                   
$lines[] = $fields;
                }
                return 
$lines;
            }
?>
2012-09-04 19:42:46
http://php5.kiev.ua/manual/ru/function.str-getcsv.html
Автор:
Note: The function trims all values unlike  str_getcsv (v5.3).
/**
  * @link https://github.com/insteps/phputils (for updated code)
  * Parse a CSV string into an array for php 4+.
  * @param string $input String
  * @param string $delimiter String
  * @param string $enclosure String
  * @return array
  */
function str_getcsv4($input, $delimiter = ',', $enclosure = '"') {

    if( ! preg_match("/[$enclosure]/", $input) ) {
      return (array)preg_replace(array("/^\\s*/", "/\\s*$/"), '', explode($delimiter, $input));
    }

    $token = "##"; $token2 = "::";
    //alternate tokens "\034\034", "\035\035", "%%";
    $t1 = preg_replace(array("/\\\[$enclosure]/", "/$enclosure{2}/",
         "/[$enclosure]\\s*[$delimiter]\\s*[$enclosure]\\s*/", "/\\s*[$enclosure]\\s*/"),
         array($token2, $token2, $token, $token), trim(trim(trim($input), $enclosure)));

    $a = explode($token, $t1);
    foreach($a as $k=>$v) {
        if ( preg_match("/^{$delimiter}/", $v) || preg_match("/{$delimiter}$/", $v) ) {
            $a[$k] = trim($v, $delimiter); $a[$k] = preg_replace("/$delimiter/", "$token", $a[$k]); }
    }
    $a = explode($token, implode($token, $a));
    return (array)preg_replace(array("/^\\s/", "/\\s$/", "/$token2/"), array('', '', $enclosure), $a);

}

if ( ! function_exists('str_getcsv')) {
  function str_getcsv($input, $delimiter = ',', $enclosure = '"') {
    return str_getcsv4($input, $delimiter, $enclosure);
  }
}
2013-03-06 03:20:46
http://php5.kiev.ua/manual/ru/function.str-getcsv.html
Автор:
<?php
Note
The function trims all values unlike  str_getcsv (v5.3).
/**
  * @link https://github.com/insteps/phputils (for updated code)
  * Parse a CSV string into an array for php 4+.
  * @param string $input String
  * @param string $delimiter String
  * @param string $enclosure String
  * @return array
  */
function str_getcsv4($input$delimiter ','$enclosure '"') {

    if( ! 
preg_match("/[$enclosure]/"$input) ) {
      return (array)
preg_replace(array("/^\\s*/""/\\s*$/"), ''explode($delimiter$input));
    }

   
$token "##"$token2 "::";
   
//alternate tokens "\034\034", "\035\035", "%%";
   
$t1 preg_replace(array("/\\\[$enclosure]/""/$enclosure{2}/",
         
"/[$enclosure]\\s*[$delimiter]\\s*[$enclosure]\\s*/""/\\s*[$enclosure]\\s*/"),
         array(
$token2$token2$token$token), trim(trim(trim($input), $enclosure)));

   
$a explode($token$t1);
    foreach(
$a as $k=>$v) {
        if ( 
preg_match("/^{$delimiter}/"$v) || preg_match("/{$delimiter}$/"$v) ) {
           
$a[$k] = trim($v$delimiter); $a[$k] = preg_replace("/$delimiter/""$token"$a[$k]); }
    }
   
$a explode($tokenimplode($token$a));
    return (array)
preg_replace(array("/^\\s/""/\\s$/""/$token2/"), array(''''$enclosure), $a);

}

if ( ! 
function_exists('str_getcsv')) {
  function 
str_getcsv($input$delimiter ','$enclosure '"') {
    return 
str_getcsv4($input$delimiter$enclosure);
  }
}
?>
2013-03-06 03:31:00
http://php5.kiev.ua/manual/ru/function.str-getcsv.html
Like some other users here noted, str_getcsv() cannot be used if you want to comply with either the RFC or with most spreadsheet tools like Excel or Google Docs.

These tools do not escape commas or new lines, but instead place double-quotes (") around the field. If there are any double-quotes in the field, these are escaped with another double-quote (" becomes ""). All this may look odd, but it is what the RFC and most tools do ... 

For instance, try exporting as .csv a Google Docs spreadsheet (File > Download as > .csv) which has new lines and commas as part of the field values and see how the .csv content looks, then try to parse it using str_getcsv() ... it will spectacularly regardless of the arguments you pass to it.

Here is a function that can handle everything correctly, and more:

- doesn't use any for or while loops,
- it allows for any separator (any string of any length),
- option to skip empty lines,
- option to trim fields,
- can handle UTF8 data too (although .csv files are likely non-unicode).

Here is the more human readable version of the function:

<?php

// returns a two-dimensional array or rows and fields

function parse_csv ($csv_string$delimiter ","$skip_empty_lines true$trim_fields true)
{
   
$enc preg_replace('/(?<!")""/''!!Q!!'$csv_string);
   
$enc preg_replace_callback(
       
'/"(.*?)"/s',
        function (
$field) {
            return 
urlencode(utf8_encode($field[1]));
        },
       
$enc
   
);
   
$lines preg_split($skip_empty_lines ? ($trim_fields '/( *\R)+/s' '/\R+/s') : '/\R/s'$enc);
    return 
array_map(
        function (
$line) use ($delimiter$trim_fields) {
           
$fields $trim_fields array_map('trim'explode($delimiter$line)) : explode($delimiter$line);
            return 
array_map(
                function (
$field) {
                    return 
str_replace('!!Q!!''"'utf8_decode(urldecode($field)));
                },
               
$fields
           
);
        },
       
$lines
   
);
}

?>

Since this is not using any loops, you can actually write it as a one-line statement (one-liner).

Here's the function using just one line of code for the function body, formatted nicely though:

<?php

// returns the same two-dimensional array as above, but with a one-liner code

function parse_csv ($csv_string$delimiter ","$skip_empty_lines true$trim_fields true)
{
    return 
array_map(
        function (
$line) use ($delimiter$trim_fields) {
            return 
array_map(
                function (
$field) {
                    return 
str_replace('!!Q!!''"'utf8_decode(urldecode($field)));
                },
               
$trim_fields array_map('trim'explode($delimiter$line)) : explode($delimiter$line)
            );
        },
       
preg_split(
           
$skip_empty_lines ? ($trim_fields '/( *\R)+/s' '/\R+/s') : '/\R/s',
           
preg_replace_callback(
               
'/"(.*?)"/s',
                function (
$field) {
                    return 
urlencode(utf8_encode($field[1]));
                },
               
$enc preg_replace('/(?<!")""/''!!Q!!'$csv_string)
            )
        )
    );
}

?>

Replace !!Q!! with another placeholder if you wish.

Have fun.
2013-03-14 01:19:04
http://php5.kiev.ua/manual/ru/function.str-getcsv.html
Автор:
@normadize - that is a nice start, but it fails on situations where a field is empty but quoted (returning a string with one double quote instead of an empty string) and cases like """""foo""""" that should result in ""foo"" but instead return "foo". I also get a row with 1 empty field at the end because of the final CRLF in the CSV. Plus, I don't really like the !!Q!! magic or urlencoding to get around things. Also, \R doesn't work in pcre on any of my php installations.

Here is my take on this, without anonymous functions (so it works on PHP < 5.3), and without your options (because I believe the only correct way to parse according to the RFC would be $skip_empty_lines = false and $trim_fields = false).

//parse a CSV file into a two-dimensional array
//this seems as simple as splitting a string by lines and commas, but this only works if tricks are performed
//to ensure that you do NOT split on lines and commas that are inside of double quotes.
function parse_csv($str)
{
    //match all the non-quoted text and one series of quoted text (or the end of the string)
    //each group of matches will be parsed with the callback, with $matches[1] containing all the non-quoted text,
    //and $matches[3] containing everything inside the quotes
    $str = preg_replace_callback('/([^"]*)("((""|[^"])*)"|$)/s', 'parse_csv_quotes', $str);

    //remove the very last newline to prevent a 0-field array for the last line
    $str = preg_replace('/\n$/', '', $str);

    //split on LF and parse each line with a callback
    return array_map('parse_csv_line', explode("\n", $str));
}

//replace all the csv-special characters inside double quotes with markers using an escape sequence
function parse_csv_quotes($matches)
{
    //anything inside the quotes that might be used to split the string into lines and fields later,
    //needs to be quoted. The only character we can guarantee as safe to use, because it will never appear in the unquoted text, is a CR
    //So we're going to use CR as a marker to make escape sequences for CR, LF, Quotes, and Commas.
    $str = str_replace("\r", "\rR", $matches[3]);
    $str = str_replace("\n", "\rN", $str);
    $str = str_replace('""', "\rQ", $str);
    $str = str_replace(',', "\rC", $str);

    //The unquoted text is where commas and newlines are allowed, and where the splits will happen
    //We're going to remove all CRs from the unquoted text, by normalizing all line endings to just LF
    //This ensures us that the only place CR is used, is as the escape sequences for quoted text
    return preg_replace('/\r\n?/', "\n", $matches[1]) . $str;
}

//split on comma and parse each field with a callback
function parse_csv_line($line)
{
    return array_map('parse_csv_field', explode(',', $line));
}

//restore any csv-special characters that are part of the data
function parse_csv_field($field) {
    $field = str_replace("\rC", ',', $field);
    $field = str_replace("\rQ", '"', $field);
    $field = str_replace("\rN", "\n", $field);
    $field = str_replace("\rR", "\r", $field);
    return $field;
}
2013-09-13 23:00:26
http://php5.kiev.ua/manual/ru/function.str-getcsv.html
Автор:
str_getcsv can be really fussy about trailing spaces - it will not necessarily recognise a final element in a quote delimited set of strings with a space following the final string for example. Using trim() before str_getcsv() quickly fixes this.
2014-02-11 15:51:47
http://php5.kiev.ua/manual/ru/function.str-getcsv.html
Optimized JayWilliams function a little bit:

<?php
function csv_to_array($filename$delimiter=','$enclosure='"'$escape '\\')
{
  if(!
file_exists($filename) || !is_readable($filename)) return false;

 
$header null;
 
$data = array();
 
$lines file($filename);

  foreach(
$lines as $line) {
   
$values str_getcsv($line$delimiter$enclosure$escape);
    if(!
$header$header $values;
    else 
$data[] = array_combine($header$values);
  }

  return 
$data;
}
?>
2014-03-21 19:11:44
http://php5.kiev.ua/manual/ru/function.str-getcsv.html
[Editor's Note (cmb): that does not produce the desired results, if fields contain linebreaks.]

Handy one liner to parse a CSV file into an array

<?php

$csv 
array_map('str_getcsv'file('data.csv'));

?>
2014-04-03 13:24:22
http://php5.kiev.ua/manual/ru/function.str-getcsv.html
I always use this:

function convert_to_csv($input_array, $output_file_name, $delimiter)
{
    /** open raw memory as file, no need for temp files */
    $temp_memory = fopen('php://memory', 'w');
    /** loop through array */
    foreach ($input_array as $line) {
        /** default php csv handler **/
        fputcsv($temp_memory, $line, $delimiter);
    }
    /** rewrind the "file" with the csv lines **/
    fseek($temp_memory, 0);
    /** modify header to be downloadable csv file **/
    header('Content-Type: application/csv');
    header('Content-Disposition: attachement; filename="' . $output_file_name . '";');
    /** Send file to browser for download */
    fpassthru($temp_memory);
}

/** Array to convert to csv */
$array_to_csv = Array(Array(12566, 'Enmanuel', 'Corvo'), Array(56544, 'John', 'Doe'), Array(78550, 'Mark', 'Smith'));
convert_to_csv($array_to_csv, 'report.csv', ',');

you can read the full post here:

<a href="http://webtricksandtreats.com/export-to-csv-php/">PHP to CSV  Download </a>
2014-09-02 23:49:44
http://php5.kiev.ua/manual/ru/function.str-getcsv.html
I wanted the best of the 2 solutions by james at moss dot io and Jay Williams (csv_to_array()) - create associative array from a CSV file with a header row.

<?php

$array 
array_map('str_getcsv'file('data.csv'));

$header array_shift($array);

array_walk($array'_combine_array'$header);

function 
_combine_array(&$row$key$header) {
 
$row array_combine($header$row);
}

?>

Then I thought why not try some benchmarking? I grabbed a sample CSV file with 50,000 rows (10 columns each) and Vulcan Logic Disassembler (VLD) which hooks into the Zend Engine and dumps all the opcodes (execution units) of a script - see http://pecl.php.net/package/vld and example here: http://fabien.potencier.org/article/8/print-vs-echo-which-one-is-faster

Result: 

array_walk() and array_map() - 39 opcodes
csv_to_array() - 69 opcodes
2014-09-21 09:06:13
http://php5.kiev.ua/manual/ru/function.str-getcsv.html
`durik at 3ilab dot net` brings up a good point but the solution provided may fail in certain (very rare) edge cases. I believe a more perfect solution is as follows:

<?php
// Use an I/O stream instead of an actual file.
$handle fopen('php://temp/myCSV''w+b');

// Write all the data to it
fwrite($handle$CSVString);

// Rewind for reading
rewind($handle);

// use fgetcsv which tends to work better than str_getcsv in some cases
$rows = array();
while (
$row fgetcsv($handle)) $rows[] = $row;
?>

A variation on this technique can also be used to implement an 'str_putcsv' which PHP lacks.
2015-02-12 12:58:30
http://php5.kiev.ua/manual/ru/function.str-getcsv.html
Автор:
PHP is failing when parsing UTF-8 with Byte Order Mark. Strip it with this one from string before passing it to csv parser:

<?php
        $bom 
pack('CCC'0xEF0xBB0xBF);
        if (
strncmp($yourString$bom3) === 0) {
           
$body substr($yourString3);
        }
?>
2015-02-24 16:53:18
http://php5.kiev.ua/manual/ru/function.str-getcsv.html
Quick and proper way:

    $temp = fopen('php://temp', 'r+');
    fputs($csvString, $temp);
    rewind($temp);

    $csvArray = array();

    while( $csvRow = fgetcsv($temp) )
        $csvArray[] = $csvRow;
    fclose($temp);
2015-05-06 13:02:53
http://php5.kiev.ua/manual/ru/function.str-getcsv.html
I prepared some better function for parsing CSV string.

function csv_to_array($string='', $row_delimiter=PHP_EOL, $delimiter = "," , $enclosure = '"' , $escape = "\\" )
{
    $rows = array_filter(explode($row_delimiter, $string));
    $header = NULL;
    $data = array();

    foreach($rows as $row)
    {
        $row = str_getcsv ($row, $delimiter, $enclosure , $escape);

        if(!$header)
            $header = $row;
        else
            $data[] = array_combine($header, $row);
    }

    return $data;
}
2015-05-28 11:08:05
http://php5.kiev.ua/manual/ru/function.str-getcsv.html
> 49 durik at 3ilab dot net /  4 years ago
$rows = str_getcsv($csv_data, "\n");
- bug, data in csv can have "\n"
'aaa','bb
b','ccc'
2015-07-02 13:21:41
http://php5.kiev.ua/manual/ru/function.str-getcsv.html
Based on James' line, this will create an array of associative arrays with the first row column headers as the keys.

<?php
    $csv 
array_map('str_getcsv'file($file));
   
array_walk($csv, function(&$a) use ($csv) {
     
$a array_combine($csv[0], $a);
    });
   
array_shift($csv); # remove column header
?> 

This will yield something like
    [2] => Array
        (
            [Campaign ID] => 295095038
            [Ad group ID] => 22460178158
            [Keyword ID] => 3993587178
2015-07-23 21:12:46
http://php5.kiev.ua/manual/ru/function.str-getcsv.html
Автор:
how to solve the UTF-8 BOM's problem
如何处理UTF-8编码的CSV文件中的BOM问题
$bom =( chr(0xEF) . chr(0xBB) . chr(0xBF) ); //define bom
$f = file_get_contents('a.csv'); //open the CSV file
#$csv = str_getcsv($f); //it will have bom  这样会出现bom的问题
$csv = str_getcsv(str_replace($bom,'',$f)); //replace the bom 替换掉bom
var_dump($csv);  //dump 输出
2016-12-21 15:25:25
http://php5.kiev.ua/manual/ru/function.str-getcsv.html
Автор:
public function csv_to_array($filename = '', $delimiter = ',', $boolean_include_title_row = false, $field_names = array()){

        try {

            if (!file_exists($filename) || !is_readable($filename)) {
                return false;
            }

            if (is_array($field_names) && !empty($field_names)) {
                $header = $field_names;
            } elseif (is_string($field_names) && (strlen($field_names) > 0)) {
                $header = explode(",", $field_names);
            } else {
                $header = null;
            }

            $csv = array_map('str_getcsv', file($filename));

            $data = array();

            foreach ($csv as $key => $row) {
                $data[] = array_combine($header, $row);
            }

            if (!$boolean_include_title_row) {
                unset($data[0]);
                $data = array_values($data);
            }
           
            return $data;

        } catch (Exception $e) {
            return false;
        }

    }
2017-07-21 20:46:39
http://php5.kiev.ua/manual/ru/function.str-getcsv.html
Improving James' line, now allowing to set the delimiter.

$csv = array_map(function($v){return str_getcsv($v, ';');}, file('data.csv'));
2019-09-26 14:15:11
http://php5.kiev.ua/manual/ru/function.str-getcsv.html
Автор:
Note that the function does NOT remove the escaping characters. If you do

<?php
str_getcsv
('"abc\"abc"')
?>

you'll get an array with a string(8) "abc\"abc", the \ will stay.
2020-04-09 09:58:09
http://php5.kiev.ua/manual/ru/function.str-getcsv.html
Sometimes the enclosure parameter of the str_getcsv function doesn't work, so I wrote a function that is equivalent to the function

<?php
/**
     * @param string $input
     * @param string $delimiter
     * @param string $enclosure
     * @param string $escape
     * @return array
     * @author TXX
     * @date   2021/1/25 15:03
     */
   
function my_str_getcsv($input$delimiter ','$enclosure '"'$escape '\\') {
       
$output = array();

        if (empty(
$input) || !is_string($input)) {
            return 
$output;
        }

        if (
preg_match("/"$escape $enclosure ."/"$input)) {
            while (
$strlen strlen($input)) {
               
$pos_delimiter       strpos($input$delimiter);    //分隔符出现位置
               
$pos_enclosure_start strpos($input$enclosure);    //封闭符-开始出现位置

                //有封闭符并封闭符在分隔符之前
               
if (is_int($pos_delimiter) && is_int($pos_enclosure_start) && $pos_enclosure_start $pos_delimiter) {
                   
$pos_enclosure_start += 1;
                   
$enclosed_str substr($input$pos_enclosure_start);    //封闭字符串-开始
                   
$pos_enclosure_end strpos($enclosed_str$enclosure);    //封闭符-结尾封闭字符串-开始中出现位置
                   
$pos_enclosure_end += $pos_enclosure_start;    //封闭符-结尾在原始数据中出现位置

                   
if ($pos_enclosure_end $pos_delimiter) {
                       
//封闭符-结束在分隔符之前,无需进行封闭
                       
$output[] = substr($input0$pos_delimiter);
                       
$offset $pos_delimiter 1;
                    } else {
                       
//封闭符-结束在分隔符之后,需要封闭
                       
$pos_enclosure_end += 1;
                       
$before_enclosed_str substr($input0$pos_enclosure_end);
                       
$enclosed_str substr($input$pos_enclosure_end);    //封闭字符串之后的字符串

                       
$enclosed_arr my_str_getcsv($enclosed_str$delimiter$enclosure);    //将封闭之后的字符串执行自身
                       
$enclosed_arr[0] = $before_enclosed_str $enclosed_arr[0];

                       
$output array_merge($output$enclosed_arr);
                       
$offset strlen($input);    //光标移至结尾
                   
}
                } else {
                   
//无封闭
                   
if (!is_int($pos_delimiter)) {
                       
//无分隔符,直接将字符串加入输出数组
                       
$output[] = $input;
                       
//光标移至结尾
                       
$offset strlen($input);
                    } else if (
$input == $delimiter) {
                       
//如果字符串只剩下分隔符,需保存'',''
                       
$output array_merge($output, ['','']);
                       
$offset $pos_delimiter+1;    //光标移至分隔符后一位
                   
} else {
                       
$output[] = substr($input0$pos_delimiter);    //将分割符之前的数据
                       
$offset $pos_delimiter+1;    //光标移至分隔符后一位
                   
}
                }
               
//将字符串更新至光标位置
               
$input substr($input,$offset);
            }
        } else {
           
//字符串中不存在封闭符,直接通过分隔符分割
           
$input preg_split("/"$escape $delimiter ."/"$input);

            if (
is_array($input)) {
               
$output $input;
            }
        }

        return 
$output;
    }

?>
2021-01-25 08:05:16
http://php5.kiev.ua/manual/ru/function.str-getcsv.html
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 using str_getcsv(). Just simply insert a CSV URL or comma separated text and it work nicely.

<?php
function parse_csv$filename_or_text$delimiter=','$enclosure='"'$linebreak="\n" )
{
   
$return = array();
   
    if(
false !== ($csv = (filter_var($filename_or_textFILTER_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;
}
?>
2021-03-18 12:43:10
http://php5.kiev.ua/manual/ru/function.str-getcsv.html
Автор:
For completeness, here is a userspace str_putcsv() that is fully compatible with fgetcsv() and fputcsv()'s arguments. Namely $escape and $eol, which all others seem to be omitting.

<?php

function str_putcsv(
    array 
$fields,
   
string $separator ",",
   
string $enclosure "\"",
   
string $escape "\\",
   
string $eol "\n"
) {
    return 
implode($separator,
       
array_map(
            function(
$a)use($enclosure$escape) {
               
$type gettype($a);
                switch(
$type) {
                    case 
'integer': return sprintf('%d'$a);
                    case 
'double':  return rtrim(sprintf('%0.'.ini_get('precision').'f'$a), '0');
                    case 
'boolean': return ( $a 'true' 'false' );
                    case 
'NULL':    return '';
                    case 
'string':
                        return 
sprintf('"%s"'str_replace(
                            [
$escape$enclosure],
                            [
$escape.$escape$escape.$enclosure],
                           
$a
                       
));
                    default: throw new 
TypeError("Cannot stringify type: $type");
                }
            },
           
$fields
       
)
    ) . 
$eol;
}
2022-10-27 00:34:05
http://php5.kiev.ua/manual/ru/function.str-getcsv.html
Автор:
I can’t see this mentioned in the description, but it appears that the fields will be trimmed slightly of trailing line breaks.

In the following example:

<?php
    $string 
"\nPHP\r\n,Java\nScript\r\n\r\n,Fortran\n,Cobol\n\n,\nSwift\r\n\r\n\r\n";
   
$data str_getcsv($string);
    foreach(
$data as $d) print "[$d]";

/*  Result:
    ================================================
    [
    PHP][Java
    Script
    ][Fortran][Cobol
    ][
    Swift
    ]
    ================================================ */
?>

You’ll see:

-    a leading line break is retained; a line break in the rest of the field is also retained
-    one trailing line break is removed; any more are retained
-    a line break at the end of the string is also removed; this means that two trailing line breaks at the end are removed
-    a line break can be a unix/macos line break (\n) or a windows line beak (\r\n)

Tested on my Macintosh, so I’m not sure how universal this is.

Among other things, it means you can read the file with the file() function without having to include the FILE_IGNORE_NEW_LINES flag.
2023-10-15 09:24:44
http://php5.kiev.ua/manual/ru/function.str-getcsv.html
old MacOS (up to ~2001) and old Office For MacOS (up to 2007? I think) use carriage-return for newlines, 
Microsoft Windows use carriage-return+line-feed for newlines,
Unix (Linux and modern MacOS) use line-feeds, 
Some systems use BOM/byte-order-masks just to say they use UTF-8, i've even encountered one-BOM-per-CSV-row!

For a csv-file parser handling all the above cases, I wrote:

<?php
function parse_csv(string $csvstring $separator ","): array
{
   
$csv strtr(
       
$csv,
        [
           
"\xEF\xBB\xBF" => ""// remove UTF-8 byte order masks, if present
           
"\r\n" => "\n"// Windows CrLf=> Unix Lf
           
"\r" => "\n" // old-MacOS Cr => Unix Lf
            // (both modern MacOS and Linux use Lf .. Windows is the only outlier)
       
]
    );
   
$lines explode("\n"$csv);
   
$keys str_getcsv(array_shift($lines), $separator);
   
$ret = array();
    foreach (
$lines as $lineno => $line) {
        if (
strlen($line) < 1) {
           
// ... probably malformed csv, but we'll allow it
           
continue;
        }
       
$parsed str_getcsv($line$separator);
        if (
count($parsed) !== count($keys)) {
            throw new 
\RuntimeException("error on csv line #{$lineno}: count mismatch:" count($parsed) . ' !== ' count($keys) . ": " var_export([
               
'error' => 'count mismatch',
               
'keys' => $keys,
               
'parsed' => $parsed,
               
'line' => $line
           
], true));
        }
       
$ret[] = array_combine($keys$parsed);
    }
    return 
$ret;
}
?>
2023-10-18 13:17:38
http://php5.kiev.ua/manual/ru/function.str-getcsv.html
For maximum compatibility with standard (RFC-4180) CSV files, remember that the proprietary-escape mechanism should be disabled. i.e. set the optional 5th parameter to ""  (the empty string).
2024-01-10 01:33:46
http://php5.kiev.ua/manual/ru/function.str-getcsv.html

    Поддержать сайт на родительском проекте КГБ