如何使用 PHP 和 fgetcsv 函数从 CSV 文件创建数组

有没有人能提供一个代码,使用 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
356600 次浏览

正如你在标题中所说的,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 文件并将该行解析为数组。

我认为 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>';

我已经创建了一个函数,它将把一个 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;
}

这是个老问题,但对 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
)
)

试试这个代码:

function readCsv($file)
{
if (($handle = fopen($file, 'r')) !== FALSE) {
while (($lineArray = fgetcsv($handle, 4000)) !== FALSE) {
print_r(lineArray);
}
fclose($handle);
}
}
$arrayFromCSV =  array_map('str_getcsv', file('/path/to/file.csv'));

请在以下@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;
}

此函数将返回数组,其中 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;
}

试试这个。

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

要获得具有正确键的数组,可以尝试这样做:

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

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

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

如果希望每一行处于数组中,而每一个单元格处于数组中:

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

我用 PHP 编写了一个实用程序,可以将 CSV 数据从文件或字符串转换为对象数组,还提供了按特定列对项进行分组的选项,还可以将分隔符从逗号更改为任意字符。

例如:

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

返回: 由 CSV 制成的阵列

按实例分组:

按“品牌”栏分组

按“年”列分组

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

我处理了很多 CSV,所以这就是为什么我必须做一个一致的实用程序,而不是一个简单的一次性使用代码。

下面是一个从 CSV 文件(任何分界线)提取值到维度 (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) {
//...
}

注意: 使用 FILE_IGNORE_NEW_LINES选项可以避免在遇到新行时创建 空荡荡的单元格