【问题标题】:Detecting File Format in PHP在 PHP 中检测文件格式
【发布时间】:2013-05-26 00:20:46
【问题描述】:

我正在构建一个接受 CSV 或制表符分隔文件的工具,然后将对其进行解析并将数据数据库化。

上传的文件可以是 CSV 或制表符分隔的。

我想出了一个可行的解决方案(如下)来检测文件可能采用的格式,并想知道是否有更好的方法来解决这个问题和/或你们中的任何人如何解决同样的问题.

谢谢

<?php

$csv_comma='Fruit,Color
Apple,"Red,Green"
Tomato,"Red,Green"
Banana,Yellow
Tangerine,Orange
';


$csv_semi_colon='Fruit;Color
Apple;"Red,Green"
Tomato;"Red,Green"
Banana;Yellow
Tangerine;Orange
';


$tab_delimited='Fruit   Color
Apple   Red,Green
Tomato  Red,Green
Banana  Yellow
Tangerine   Orange';


$fileArr = array($csv_comma,$csv_semi_colon,$tab_delimited);


foreach($fileArr as $file){

   if(preg_match('/^(.+),(.+)/',trim($file))){

       echo "CSV with comma separator";

   }

   if(preg_match('/^(.+);(.+)/',trim($file))){

       echo "CSV with semi colon separator";

    }


   if(preg_match('/^(.+)\t(.+)/',trim($file))){

       echo "Tab delimited";

   }
}

【问题讨论】:

  • 任何启发式方法都会给出错误的结果。您只是无法 100% 正确地猜出使用了什么分隔符
  • Here Python 是如何做到的。
  • 为什么不尝试用fgetcsv, or ; ... etc 作为分隔符来解析csv?如果失败,则它一定不是有效的 csv。
  • 或者为什么不在您的上传表单中设置三个单选按钮,用户可以在其中指定在他们上传的文件中使用哪些分隔符...?
  • 如果你只读取文件的第一行并匹配它而不是匹配整个文件会更好 - 它会更快并且使用更少的系统资源。

标签: php regex csv


【解决方案1】:

嗯,csv 已经实现了很多。 csv 的默认值为 ,,但使用 sep= 您可以指定其他分隔符。

您可以将其实现为 csv。所以你有一个默认的,,但是如果sep被定义了,你就使用它。

您的文件可能如下所示:

apple, orange, tomato

sep=;
apple; orange; tomato

因此,如果第一行以 sep 开头,则它是“选项”行,否则存在值。对于标签你做sep=\t

现在用户可以定义自己的分隔符,不用再猜测了


在一些易于用户使用的 CBroe 之后,可能会有一些变化。 csv 只接受一个字符作为分隔符,以便系统可以像上面一样使用。 cvs 编辑器(如 excel)将为用户处理该问题

如果用户使用选项卡,它将不是 csv 文件,而是 .txt(例如)。所以你可以根据给定的文件更改默认值。

另外我想补充一点,已经在 cmets 中指出,如果你想猜测你会遇到它会发生的点,那就错了。

我不知道文件的设置,但 csv 行的长度必须相同(根据我的记忆)。所以你可以做的是读出前 x 行。并使用每个分隔符。

然后你检查哪些行长度是相同的,很可能是你的分隔符(再次猜测)

【讨论】:

  • 这需要修改 CSV 文件 - 可能不方便甚至不可能。
  • 用文本编辑器打开一个 csv 文件。您还可以使用此设置制作一个 .txt 文件。
  • “用文本编辑器打开一个 csv 文件。” - 哇,我怎么没想到呢? &lt;/sarc&gt; - 说真的,为了方便起见(“什么,我必须在上传之前修改我的文件?”)这可能不是一个选项,也不是那么精通技术的用户可能会搞砸文件同时尝试执行他们被要求的操作...所以我并不是说您的答案是错误 或不是可能的解决方案 - 只是它可能会产生比实际解决的问题更大的问题。
  • 正如我所说的 csv 的默认值是 ,。如果您更改该值,则您已经弄乱了 csv。 csv 也会自动将该 sep 放在文件的顶部。因为 csv 只能处理 1 个字符作为 sperator,所以我从未见过选项卡。因此,如果使用选项卡,则有人已经在处理文本文件了。
  • @Fred:或者按照我在对上述问题的评论中提出的建议。
【解决方案2】:

您可以使用这种模式来检查csv结构并确定分隔符:

if (preg_match('^(?:("[^"]++"|[^,;\t\n]++)(?<sep>[,\t;])(?1)(?:\n|$))++$', $csv_comma, $match))
    print_r($match['sep']);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-09-28
    • 2010-10-05
    • 1970-01-01
    • 1970-01-01
    • 2010-09-16
    • 2013-04-20
    • 2021-07-19
    相关资源
    最近更新 更多