【问题标题】:How to create an array from a CSV file using PHP and the fgetcsv function如何使用 PHP 和 fgetcsv 函数从 CSV 文件创建数组
【发布时间】:2010-11-19 03:59:34
【问题描述】:

谁能提供一个代码来使用 fgetcsv 从 CSV 文件创建一个数组?

我使用以下代码从一个简单的 CSV 文件创建了一个数组,但是当我的一个字段有多个逗号(例如地址)时,它就无法正常工作。

$lines =file('CSV Address.csv');

foreach($lines as $data)
{
list($name[],$address[],$status[])
= explode(',',$data);
}

*另外,我的托管服务不支持 str_getcsv。

以上代码不适用于以下 CSV 文件示例。第一栏是姓名,第二栏是地址,第三栏是婚姻状况。

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

【问题讨论】:

标签: php arrays csv


【解决方案1】:

就像你在标题中所说的那样,fgetcsv 是要走的路。它非常易于使用。

$file = fopen('myCSVFile.csv', 'r');
while (($line = fgetcsv($file)) !== FALSE) {
  //$line is an array of the csv elements
  print_r($line);
}
fclose($file);

如果fopen() 失败,您需要在其中进行更多错误检查,但这可以逐行读取 CSV 文件并将该行解析为数组。

【讨论】:

  • 感谢 Dave,但您的示例仅提供了具有以下三个位置的数组:$line[0]、$line[1] 和 $line[2]。这对第一行来说很好,但我需要为第二行、第三行、第四行等创建单独的位置。这样我就可以分别操纵线条。希望这是有道理的
  • @Thomas 如果您需要一组姓名、地址和状态,您可以按照上面的操作:list($names[], $addresses[], $statuses[]) = $line;
  • 我有一个关于这个函数的问题,如果其中一个 CSV 字段中有一个新行,它当前会将该行解析为单个记录吗?或者它会返回两个(损坏的)记录吗?
  • 为什么我们需要在最后关闭?
  • @angrykiwi 否则你会不必要地消耗记忆。其他进程无法访问该文件。
【解决方案2】:

我认为str_getcsv() 语法更简洁,它也不需要将 CSV 存储在文件系统中。

$csv = str_getcsv(file_get_contents('myCSVFile.csv'));

echo '<pre>';
print_r($csv);
echo '</pre>';

或逐行解决:

$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>';

或者对于没有 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>';

【讨论】:

  • 仅供参考:str_getcsv() 仅从 PHP 5.3.0 开始可用。我正在做的项目错过了 1 个版本的 DOH! (我们使用的是 5.2.9 atm)。
  • 这很好,除非你有内存限制。 fgetcsv 解决方案适用于任何硬件配置。
  • 当心! str_getcsv 存在一个错误,使其忽略行尾:bugs.php.net/bug.php?id=55763&edit=1
  • 注意你可以这样做:while(!feof($file)) { $csv[] = fgetcsv($file); } 而不是 while (($result = fgetcsv($file)) !== false) { $csv[] = $result; }
【解决方案3】:

我创建了一个将 csv 字符串转换为数组的函数。该函数知道如何转义特殊字符,并且可以使用或不使用附件字符。

$dataArray = csvstring_to_array( file_get_contents('Address.csv'));

我用你的 csv 样本试了一下,它按预期工作!

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;
}

【讨论】:

    【解决方案4】:

    老问题,但仍然适用于 PHP 5.2 用户。 str_getcsv 从 PHP 5.3 开始可用。我编写了一个与 fgetcsv 本身配合使用的小函数。

    以下是我来自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;
    }
    

    返回

    开始阅读 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
            )
    ) 
    

    【讨论】:

    • 顺便说一句,您可以将可选参数添加到 fgetcsv 以更改分隔符、附件字符等。
    【解决方案5】:

    试试这个代码:

    function readCsv($file)
    {
        if (($handle = fopen($file, 'r')) !== FALSE) {
            while (($lineArray = fgetcsv($handle, 4000)) !== FALSE) {
                print_r(lineArray);
            }
            fclose($handle);
        }
    }
    

    【讨论】:

    • 发布与提问者完全相同的答案的原因是什么?
    【解决方案6】:
    $arrayFromCSV =  array_map('str_getcsv', file('/path/to/file.csv'));
    

    【讨论】:

    • 很简洁,但是返回的是数组,不是矩阵
    【解决方案7】:

    请在下方找到来自@knagode 的函数链接,该链接通过跳过行参数进行了增强。 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;
        }
    

    【讨论】:

    • 在stackoverflow中,请详细说明而不是只提供链接。
    【解决方案8】:

    此函数将返回带有 Header 值的数组作为数组键。

    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;
        }
    

    【讨论】:

      【解决方案9】:

      试试这个..

      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
              ));
      

      【讨论】:

        【解决方案10】:

        要获得具有正确键的数组,您可以试试这个:

        // 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);
        

        【讨论】:

          【解决方案11】:

          我想出了这个非常基本的代码。我认为它对任何人都有用。

          $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);
          

          【讨论】:

            【解决方案12】:

            如果您希望每一行都在一个数组中,并且该行中的每个单元格都在数组中:

            $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);
            

            【讨论】:

              【解决方案13】:
               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;
                  }
              }
              

              【讨论】:

                【解决方案14】:
                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;
                }
                

                【讨论】:

                • 有什么问题?
                • 见“Explaining entirely code-based answers”。虽然这在技术上可能是正确的,但它并不能解释为什么它可以解决问题或应该是选择的答案。除了帮助解决问题,我们还应该进行教育。
                【解决方案15】:

                我在 PHP 中创建了一个实用程序,可以将 CSV 数据从文件或字符串转换为对象数组,还提供了按特定列对项目进行分组的选项,您还可以将分隔符从逗号更改为任何你想要的角色。

                例子:

                Brand, Model, Year
                Volkswagen, Gol,2008
                Fiat, Uno, 2007
                Fiat, Palio, 2002
                Fiat, Mobi, 2021
                Volkswagen, Jetta, 2018
                Hyunday, HB20, 2020
                

                返回: Array made out of CSV

                按示例分组:

                Grouping by the 'Brand' column

                Grouping by the 'Year' column

                您可以在这里找到代码:https://github.com/raphah96/PHPCSV

                我经常使用 CSV,这就是为什么我必须制作一个一致的实用程序而不是简单的一次性代码。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2017-01-20
                  • 1970-01-01
                  • 2017-01-04
                  • 1970-01-01
                  • 2022-11-29
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多