3

我正在使用 csv 解析器类 (http://code.google.com/p/php-csv-parser/) 来解析和提取 csv 文件中的数据。我遇到的问题是它仅适用于某些 csv 文件类型。(Mac、Ms-Dos 和 Windows 似乎都有 csv 类型。)

如果我使用使用 csv - windows 选项保存在 mac(在 excel 中)上的 csv 文件,则该代码有效。但是,如果我将 Windows 机器上的文件简单地保存为 csv,那是行不通的。(你会认为这与在 mac 上保存 csv-windows 的格式相同。)如果我将它保存为 csv-MSDOS 文件,它确实可以在 Windows 机器上工作。这似乎有点荒谬。

有没有办法标准化这三种文件类型,以便我的代码可以读取上传的任何类型的 csv?

我想它会是这样的:

$standardizedCSV = preg_replace_all('/\r[^\n]/', '\r\n', $csvContent);

我知道这与每种文件类型如何处理行尾有关,但我有点想弄清楚这些差异。如果有人有任何建议,请告诉我。

谢谢。

更新:这是我正在使用的 csv 解析器中的相关代码,它逐行提取数据:

$c = 0;
$d = $this->settings['delimiter'];
$e = $this->settings['escape'];
$l = $this->settings['length'];

$res = fopen($this->_filename, 'r');

while ($keys = fgetcsv($res, $l, $d, $e)) {

if ($c == 0) {
   $this->headers = $keys;
} else {
   array_push($this->rows, $keys);
}

$c ++;
}

我想我需要了解 fgetcsv 如何处理 eol,以便我可以确保以相同的方式处理任何格式的 csv 文件。

4

3 回答 3

2

这似乎可以解决问题:

    ini_set("auto_detect_line_endings", true);

问题在于行尾,但我不需要创建自己的 EOL 解析器。这个运行时设置为我做了。请参阅http://us.php.net/manual/en/filesystem.configuration.php#ini.auto-detect-line-endings

于 2012-08-14T02:13:58.387 回答
1

我认为行尾不是问题。CSV 的问题在于它只是一个“逗号分隔值”文件,除此之外没有标准化。所以有些系统使用逗号分隔值,有些使用分号 ( ;)。我确信有些变体甚至使用了其他值分隔符。

此外,CSV 文件之间的转义字符(通常是反斜杠\)可能不同,并且某些 CSV 文件还在每个值周围使用引号 ( ")。

CSV 文件可以使用上述之间的任何变化。例如,我相当肯定 Microsoft Excel 导出的 CSV 文件使用分号分隔值,并且值周围没有任何引号。

我确信有一些方法可以自动检测如何解析 CSV 文件,但最好的方法是让用户自行决定。这就是 Excel 所做的。

于 2012-08-10T05:22:27.907 回答
0

如果您使用 CSV 文件,您必须就许多未正确标准化的细节达成一致:

  • 行尾(Unix 0x0a、Macintosh 0x0d、DOS 0x0d 0x0a)
  • 字段分隔符(逗号、分号等)
  • 字段引用(引用所有字段,仅字符串字段,仅包含字段和行分隔符的字符串字段)
  • 在字符串字段中转义双引号(双引号加倍、双引号前的反斜杠字符等)
  • 多行字符串字段(是否允许)
  • 文件编码(ISO-8859-1、UTF-8 等)

如果您创建 CSV 阅读器,您可以自动处理行尾和字段引用的不同变化。但是其余的必须事先让 CSV 解析器知道。

事实标准是 Excel 生成的 CSV 格式。但是,Excel 使用不同的格式变体:

  • 通常是 DOS 行尾(但我从来没有用 Excel for Macintosh 尝试过)
  • 字段分隔符取决于语言环境。如果逗号用于对长数字中的数字进行分组,Excel 使用分号作为字段分隔符。否则逗号。
  • 如果需要,Excel 会使用双引号。
  • Excel 将字符串字段中的双引号加倍。
  • Excel 支持多行字符串字段。
  • 文件编码似乎是当前语言环境的文件编码。所以它会有所不同。
于 2012-08-10T05:57:45.753 回答