如何在 PHP 中解析 csv 在列中具有多行数据

Posted

技术标签:

【中文标题】如何在 PHP 中解析 csv 在列中具有多行数据【英文标题】:How to parse csv in PHP having multiline data in a column 【发布时间】:2011-06-11 14:27:48 【问题描述】:

考虑像这样的 CSV 文件

item1,"description 1"
item2,"description 2"
item3,"description 3
description 3 continues on new line"
item4,"description 4"

应该这样解析

item1,"description 1"
item2,"description 2"
item3,"description 3 description 3 continues on new line"
item4,"description 4"

有没有办法在 php 中解析这个具有多行值的 CSV?

【问题讨论】:

@goreSplatter,或者只使用现有的。 @Bart 抱歉,我遗漏了另一个明显的解决方案。 parse csv file php 的可能重复项 【参考方案1】:

这里有一些工作示例如何做到这一点。我正在使用 fgetcsv:

字符串变量 $CsvString 中的 CSV:

$fp = tmpfile();
fwrite($fp, $CsvString);
rewind($fp); //rewind to process CSV
while (($row = fgetcsv($fp, 0)) !== FALSE) 
    print_r($row);

文件中的CSV:

if (($handle = fopen("test.csv", "r")) !== FALSE) 
  while (($row = fgetcsv($handle, 0, ",")) !== FALSE) 
    print_r($row);
  
  fclose($handle);

【讨论】:

优秀的答案。我有用户上传的带有 \r 行结尾的 CSV(我不知道为什么),并且必须在解析 CSV 之前进行 strreplace。由于 str_getcsv 不处理多行,并且某些行中包含新行,因此这(虽然 hackish,将内容放在临时文件中只是为了让 PHP 解析它)可以工作。【参考方案2】:

fgetcsv 应该能够正确解析这个。 无论如何,我不建议手动执行此操作,在解析 CSV 时有很多这样的陷阱。

【讨论】:

问题是我使用 fgets 从文件中读取行,然后使用 str_getcsv 来解析字符串,而不是仅使用 fgetcsv。它适用于单行列,但不适用于多行列。甚至强硬的 PHP.net 说 fgetcsv“从文件中获取行”似​​乎这里的“行”不是纯文本文件中的实际行,而是包含所有多行数据的整个实际行。 我今天遇到了同样的问题并做了一点test,这证明了你关于 lines 指的是 csv-rows 而不是到实际的 file-lines. 我希望使用str_getcsv,因为它不必将整个文件加载到内存中,只需将红色行加载。 fgetcsv 确实适用于多行 CSV 字段,但 str_getcsv 显然不适用。 @Erfan fgetcsv 也一次只从打开的文件句柄中读取一行...!?【参考方案3】:

基于StanleyD 答案,但使用临时内存块(而不是写入磁盘)以获得更好的性能:

$fp = fopen('php://temp','r+');
fwrite($fp, $CsvString);
rewind($fp); //rewind to process CSV
while (($row = fgetcsv($fp, 0)) !== FALSE) 
    print_r($row);

【讨论】:

【参考方案4】:

这是一个使用 PHP 函数str_getcsv() 的快速简便的解决方案

这是一个例子:

function parse_csv( $filename_or_text, $delimiter=',', $enclosure='"', $linebreak="\n" )

    $return = array();
    
    if(false !== ($csv = (filter_var($filename_or_text, FILTER_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;

想象一下,您需要一个同时处理 URL 和逗号分隔文本的函数。这正是这样工作的功能。只需插入一个 CSV URL 或逗号分隔的文本,它就可以很好地工作。

【讨论】:

没有多行,见@Erfan

以上是关于如何在 PHP 中解析 csv 在列中具有多行数据的主要内容,如果未能解决你的问题,请参考以下文章

导出为 CSV 时,如何在列中保留前导零?

R:带多行文字的直方图字幕:如何在列中获得表格对齐?

熊猫在列中使用额外的逗号读取 csv

pandas中的SQL查询:根据其他列的组合在列中连接多行

MySQL:如何在列中选择具有某些值的 ID [重复]

SQL - 在列中查找具有特定值组合的行