【问题标题】:standardizing CSV file types标准化 CSV 文件类型
【发布时间】:2012-08-07 09:23:27
【问题描述】:

我正在使用 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 文件。

【问题讨论】:

  • 更新我将 csv 解析器中的相关代码添加到我的原始帖子中,以便您了解它如何处理 EOL。

标签: php excel csv


【解决方案1】:

这似乎可以解决问题:

    ini_set("auto_detect_line_endings", true);

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

【讨论】:

    【解决方案2】:

    如果您使用 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 支持多行字符串字段。
    • 文件编码似乎是当前语言环境的文件编码。所以它会有所不同。

    【讨论】:

    • 感谢您的详细回复。我确实标准化了行尾以符合 DOS 格式 - 0x0d 0x0a - 它适用于一个文件,但不适用于另一个文件。我没有查看该文件是否可能以不同的方式不合规。 - 例如,它可能使用冒号而不是逗号来描述信息。我会在早上看看,然后报告。非常感谢。
    【解决方案3】:

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

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

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

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

    【讨论】:

    • 我认为 EOL 是问题的原因是,当我的解析器运行不兼容的 cvs 类型(如上所述)时,$csvparser->headers 变量会记录整个文件 - 它不会t 只记录第一行的字段。兼容的 csv 类型非常整齐地将标题存储在 $this->headers 中,并将数据行存储在 $this->rows 中。因此,某些文件类型的 EOL 会以某种方式导致 while 循环迭代,而另一些则不会。
    • 另外 - 当我在文本编辑器中并排查看兼容和不兼容的 csv 文件类型时,它们看起来与逗号分隔的值完全相同。 (我正在使用 BBEdit 来执行此操作。)两者之间的唯一区别是 BBEdit 表示兼容版本为“Windows (CRLF)”格式 - (位于 BBEdit 窗口底部的下拉列表中。我可以但是,“看不到” EOL..
    猜你喜欢
    • 2014-11-09
    • 2013-09-09
    • 2011-07-05
    • 2015-06-14
    • 1970-01-01
    • 2021-06-01
    • 2015-09-21
    • 1970-01-01
    • 2016-08-29
    相关资源
    最近更新 更多