如何解析CSV文件以首先获取列名,然后获取与其相关的行?

27

这是我的 CSV 文件。

column1,column2,column3,column4,column5
column1_row1,column2_row1,column3_row1,column4_row1,column5_row1
column1_row2,column2_row2,column3_row2,column4_row2,column5_row2
column1_row3,column2_row3,column3_row3,column4_row3,column5_row3
column1_row4,column2_row4,column3_row4,column4_row4,column5_row4
column1_row5,column2_row5,column3_row5,column4_row5,column5_row5
column1_row6,column2_row6,column3_row6,column4_row6,column5_row6
column1_row7,column2_row7,column3_row7,column4_row7,column5_row7
column1_row8,column2_row8,column3_row8,column4_row8,column5_row8
column1_row9,column2_row9,column3_row9,column4_row9,column5_row9

第一行是列名。我试过使用 fgetcsv(),但它只会显示所有行而不是我想要的结果。我该怎么办?

如果我最终将数据放入数组中,我将能够以表格格式打印出数据,就像在 Excel 中显示的那样。

谢谢。

这是我的示例:

$filename = "upload/sample.csv";
if (($handle = fopen($filename, 'r')) !== FALSE)
{
    while (($row = fgetcsv($handle, 1000, ",")) !== FALSE) 
    {
       print_r($row);
     }
}

这是我的输出:(我将 $row 放入

 中以便显示)

Array
(
    [0] => column1
    [1] => column2
    [2] => column3
    [3] => column4
    [4] => column5
column1_row1
    [5] => column2_row1
    [6] => column3_row1
    [7] => column4_row1
    [8] => column5_row1
column1_row2
    [9] => column2_row2
    [10] => column3_row2
    [11] => column4_row2
    [12] => column5_row2
column1_row3
    [13] => column2_row3
    [14] => column3_row3
    [15] => column4_row3
    [16] => column5_row3
column1_row4
    [17] => column2_row4
    [18] => column3_row4
    [19] => column4_row4
    [20] => column5_row4
column1_row5
    [21] => column2_row5
    [22] => column3_row5
    [23] => column4_row5
    [24] => column5_row5
column1_row6
    [25] => column2_row6
    [26] => column3_row6
    [27] => column4_row6
    [28] => column5_row6
column1_row7
    [29] => column2_row7
    [30] => column3_row7
    [31] => column4_row7
    [32] => column5_row7
column1_row8
    [33] => column2_row8
    [34] => column3_row8
    [35] => column4_row8
    [36] => column5_row8
column1_row9
    [37] => column2_row9
    [38] => column3_row9
    [39] => column4_row9
    [40] => column5_row9
)

使用 fgetcsv 然后逐行遍历有什么问题吗? - Pekka
你能展示一下你的方法样例吗?然后我会指出让我困惑的地方。 - Exploit
我没有样例。你能展示一下你的样例以及哪里出了问题吗? - Pekka
如果将封闭符号(默认为“)”)设置为其他值,例如null、空字符串或类似的内容,是否有帮助? - Svish
6个回答

82

若要一次性读取所有内容,您可以使用:

$csv = array_map("str_getcsv", file("file1.csv",FILE_SKIP_EMPTY_LINES));
$keys = array_shift($csv);

要将所有行转换为一个漂亮的关联数组,你可以使用以下方法:

foreach ($csv as $i=>$row) {
    $csv[$i] = array_combine($keys, $row);
}

1
我怎么能使用分号(;)作为分隔符呢? - Michiel
这种方式无法处理单元格中的换行符。 - Michael
4
@Michiel,如何使用不同的分隔符:$file = file("file1.csv",FILE_SKIP_EMPTY_LINES); $csv = array_map("str_getcsv",$file, array_fill(0, count($file), ';')); - Tapper
1
@mario 这是我最喜欢的答案类型。简短明了,按照预期工作,并且最重要的是它教会了我新的功能。 - pzirkind
2
请注意,仅当所有数据行的长度与标题行相同时,此方法才有效。 - FKEinternet

7
// Opening the file for reading...
$fp = fopen('path_to_your_file.csv', 'r');

// Headrow
$head = fgetcsv($fp, 4096, ';', '"');

// Rows
while($column = fgetcsv($fp, 4096, ';', '"'))
{
    // This is a great trick, to get an associative row by combining the headrow with the content-rows.
    $column = array_combine($head, $column);

    echo $column['column1'];
}

我尝试了你的示例,但没有得到任何输出。你知道为什么吗? - Exploit
只有当你的列名为“column1”,“column2”等,就像你的示例中一样,才能正常工作。 echo $column ['the_name_of_your_column_in_the_headrow']; - Fidi
是的,我试过了,没有输出,所以我打印了$column,什么也没有。这是pastie链接:http://pastie.org/1796761 - Exploit
你是否启用了error_reporting?如果没有,请启用并查看是否出现错误。你能到达while循环吗?将die(x);调试代码粘贴到循环中,以查看它是否被执行。如果没有执行,则文件为空或文件指针($fp)未设置(例如无效路径)。 - Fidi
任何卡在5.3之前的人都可以采用这个好的解决方案。 - Cups
这比接受的响应更节省内存。 - Yoann

1

I made this quick solution using fgetcsv, works fine and it's easier to read and understand. Then the whole result is saved in the $csv array

$csv = array();
$i = 0;
if (($handle = fopen($upload['file'], "r")) !== false) {
    $columns = fgetcsv($handle, 1000, ",");
    while (($row = fgetcsv($handle, 1000, ",")) !== false) {
        $csv[$i] = array_combine($columns, $row);
        $i++;
    }
    fclose($handle);
}


0

你不能只调用一次fgetcsv来获取标题,然后开始循环获取其余部分吗?

修改了在手册中找到的示例。它应该输出一个带有标题和值的表格。

<?php
$row = 1;
if (($handle = fopen('test.csv', 'r')) !== FALSE)
{
    echo '<table>';

    // Get headers
    if (($data = fgetcsv($handle, 1000, ',')) !== FALSE)
    {
        echo '<tr><th>'.implode('</th><th>', $data).'</th></tr>';
    }

    // Get the rest
    while (($data = fgetcsv($handle, 1000, ',')) !== FALSE)
    {
        echo '<tr><td>'.implode('</td><td>', $data).'</td></tr>';
    }
    fclose($handle);
    echo '</table>';
}
?>

@Sarmen:添加了示例。尽管我没有测试过,但如果可以的话请告诉我。 - Svish
我添加了我尝试的内容。 - Exploit

0

我修改了第一个答案,以更好地处理不同的列分隔符

if (($handle = fopen("hdbsource/products_stock.csv", "r")) !== FALSE) {
    while (($csv[] = fgetcsv($handle, 1000, ',')) !== FALSE) {}
    fclose($handle);
}
$keys = array_shift($csv);

foreach ($csv as $i=>$row) {
    $csv[$i] = array_combine($keys, $row);
}

这对我没用。 - Scott Fleming

0

看起来它可能把所有内容都当作一行。也许你的 CSV 文件的换行符与应该有的不同?至少在你的输出中是这样的。如果你查看结果数组中的第1行第5列,它包含一个换行符和第2行第1列相同。其余的也是如此。它将所有内容读取为一行。

注意:如果 PHP 在读取由 Macintosh 计算机创建或上载的文件时没有正确识别行尾,启用 auto_detect_line_endings 运行时配置选项可能有助于解决问题。-- fgetscv

你在哪个平台上?无论如何,请检查行尾。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接