【问题标题】:Reading .csv into a PHP array [duplicate]将.csv读入PHP数组[重复]
【发布时间】:2015-06-25 00:09:17
【问题描述】:

我有一个 PHP 例程,它读取已上传到我的站点的 .csv 文件。

文件中的字段数可能因上传而异。

我希望能够确定 .csv 文件的大小(字段数),然后将其内容存储在一个数组中。

这是我目前所拥有的:

//get the csv file 
$file = $_FILES[csv1][tmp_name]; 
$handle = fopen($file,"r"); 

//loop through the csv file and insert into array
$dataline = fgetcsv($handle,1000,",","'");
$fieldnum = count($dataline);

$recordloop = 0;

while ($dataline) 
{ 

    for ($fieldloop=0; $fieldloop <$fieldnum; $fieldloop++)
    {
        //this is the bit that is wrong
        $dataarray[]=array($dataline[$fieldloop]);
    }

    $data = fgetcsv($handle,1000,",","'");
    $recordloop++;
}

例如,如果有 30 个字段和 200 条记录,我试图让数组成为结构 $dataarray[200][30]

如何将数据放入此结构的数组中?

示例 .csv:

Row 1 will be field headings
Name, Gender, Ethnicity, DOB, etc .... the number of fields is not fixed - it could be from 30 to 40 fields in this row

Rows 2 onwards will be the records
John, M, British, 10/04/49, etc
Simon, M, British, 04/03/65, etc

回答 - 做了我想做的事

$file = $_FILES[csv1][tmp_name]; 
$handle = fopen($file,"r"); 

$matrix = array();
while (($row = fgetcsv($handle, 1000, ",")) !== FALSE) 
{
$matrix[] = $row;
}

【问题讨论】:

标签: php arrays algorithm csv multidimensional-array


【解决方案1】:

您已经在 PHP 中实现了这种实现:

$csv = array_map('str_getcsv', file('someCSVfile.csv'));

解释:

  • str_getcsv() - 将 CSV 字符串解析为数组。
  • file() - 将整个文件读入一个数组。
  • array_map(Function, Array)- 在对每个元素应用回调函数后,返回一个包含数组所有元素的数组。

示例输出:

//CSV
NAME,CLASS,ROOM
Sally,2018,312
Belinda,2017,148

//OUTPUT:
Array(
       [0] => Array([0] => NAME,    [1] => CLASS, [2] => ROOM), 
       [1] => Array([0] => Sally,   [1] => 2018,  [2] => 312),
       [2] => Array([0] => Belinda, [1] => 2017,  [2] => 148)
)

关联键

使用关联键解析的两个快速函数 - 均基于 array_map 方法:

方法一:运行两次

function assoc_getcsv($csv_path) {
    $r = array_map('str_getcsv', file($csv_path));
    foreach( $r as $k => $d ) { $r[$k] = array_combine($r[0], $r[$k]); }
    return array_values(array_slice($r,1));
}  

方法2:运行一次

function assoc_getcsv($csv_path) {
    $f = array();
    function parse_csv_assoc($str,&$f){ 
        if (empty($f)) { $f = str_getcsv($str); }
        return array_combine($f, str_getcsv($str));         
    }
    return array_values(array_slice(array_map('parse_csv_assoc', file($csv_path), $f),1));
} 

示例输出:

//CSV
NAME,CLASS,ROOM
Sally,2018,312
Belinda,2017,148

//OUTPUT:
Array(
       [0] => Array([NAME] => Sally,   [CLASS] => 2018,  [ROOM] => 312),
       [1] => Array([NAME] => Belinda, [CLASS] => 2017,  [ROOM] => 148)
)

【讨论】:

  • 这是完成工作的一种有趣的简短方法。只是出于好奇 - 你有没有比较过这个速度和使用 SplFileObjectIterator 的速度?
  • 否 -> 我在一个月内使用此功能并在 ~1-2 秒内解析 11K CSV
  • 这绝对是使用SplFileObject 的两倍。这是我的test
  • @tftd 很棒的测试!你也准备测试另外两种方法吗?
【解决方案2】:

这个函数会读取一个CSV并生成一个多维数组

function fromCSVFile( $file) {
    // open the CVS file
    $handle = @fopen( $file, "r");
    if ( !$handle ) {
        throw new \Exception( "Couldn't open $file!" );
    }

    $result = [];

    // read the first line
    $first = strtolower( fgets( $handle, 4096 ) );
    // get the keys
    $keys = str_getcsv( $first );

    // read until the end of file
    while ( ($buffer = fgets( $handle, 4096 )) !== false ) {

        // read the next entry
        $array = str_getcsv ( $buffer );
        if ( empty( $array ) ) continue;

        $row = [];
        $i=0;

        // replace numeric indexes with keys for each entry
        foreach ( $keys as $key ) {
            $row[ $key ] = $array[ $i ];
            $i++;
        }

        // add relational array to final result
        $result[] = $row;
    }

    fclose( $handle );
    return $result;
}

如果您的 .CSV 文件如下所示:

Name,Gender,Ethnicity,DOB
John,M,British,10/04/49
Simon,M,British,04/03/65

你会得到这个:

(
    [0] => Array
        (
            [name] => John
            [gender] => M
            [ethnicity] => British
            [dob] => 10/04/49
        )

    [1] => Array
        (
            [name] => Simon
            [gender] => M
            [ethnicity] => British
            [dob] => 04/03/65
        )

)

【讨论】:

  • 谢谢,这很好,但我实际上并不希望第一行成为关键。我希望它们保留在数组的第一行。
【解决方案3】:

1.csv:

Name,Gender,Ethnicity,DOB
John,M,British,10/04/49
Simon,M,British,04/03/65

使用 file() 将 csv 文件读入一个数组,然后遍历该数组并将所有字段放入一个带有 explode() 的数组元素中,并创建新的 $array

<?php

$file = '1.csv';
$content = file($file);

$array = array();

for($i = 1; $i < count($content); $i++) {
    $line = explode(',', $content[$i]);
    for($j = 0; $j < count($line); $j++) {
        $array[$i][$j + 1] = $line[$j];
    }   
}   

print_r($array);

?>

输出:

Array
(
    [1] => Array
        (
            [1] => John
            [2] => M
            [3] => British
            [4] => 10/04/49

        )

    [2] => Array
        (
            [1] => Simon
            [2] => M
            [3] => British
            [4] => 04/03/65

        )

)

如果你想得到 record:2field:4 你可以这样做:

echo $array[2][4];

输出:

04/03/65

【讨论】:

  • @RichardGriffiths 你有预付款吗?
  • ? - 我找到了答案。我已经编辑了问题以显示答案。感谢您的帮助。
猜你喜欢
  • 2017-06-07
  • 1970-01-01
  • 2023-03-23
  • 1970-01-01
  • 2011-06-07
  • 2018-11-07
  • 1970-01-01
  • 1970-01-01
  • 2020-07-10
相关资源
最近更新 更多