2013-02-19 57 views
2

注意:我首先说我知道我可能错过了一些非常明显的东西。我在其中的一种编码朦胧中无法看到简单的解决方案。在PHP中确定.csv分隔符

Issue:我已经在PHP中编写脚本来解析.csv文件,选择包含电子邮件地址的列,并将它们放入数据库中。现在,我发现用户正尝试上传具有.csv文件类型的文件,但实际上并未用逗号分隔。我正在尝试编写一个能够正确确定分隔符(制表符,换行符,空格等)的函数,但遇到了一些问题。我想我想获得所有这些地址的数组,以便按键的数量可以将分号添加到该分隔符。

代码:

$filename = "../some/path/test.csv"; 
if (($handle = fopen($fileName, "r")) !== FALSE) { 
    $delimiters = array(',', ' ', "\t", "\n"); 
    $delimNum = 0; 
    foreach ($delimiters as $delimiter) { 
     $row = 0; 
     while (($data = fgetcsv($handle, 1000, $delimiter)) !== FALSE) { 
     $data = (string)$data[0]; 
     $delimiterList[$delimNum] = explode($delimiter, $data); 
     $row++; 
    } 
    $delimNum++; 
} 
die(print_r($delimiterList)); 
} 

结果:

Array 
(
[0] => Array 
    (
     [0] => email 
[email protected] 
[email protected] 
[email protected] 
[email protected] 
[email protected] 
[email protected] 
[email protected] 
[email protected] 
[email protected] 
[email protected] 
[email protected] 
    ) 
) 

就像我说的,我知道这可能是解决这个错误的方式,所以我很感激任何你可以提供的见解!

+1

你总是可以添加其他输入允许用户指定分隔符。 – Supericy 2013-02-19 00:56:54

+0

我认为@Supericy的想法是最好的,这似乎并不像你可以轻易确定的东西,除非你有某种基础从头开始。 – 2013-02-19 00:58:24

+0

Duplicate:http://stackoverflow.com/questions/3395267/how-to-find-out-if-csv-file-fields-are-tab-delimited-or-comma-delimited – 2015-12-04 14:53:19

回答

1

用可用性而不是代码解决这个问题。让用户选择分隔符。

但是,由于他们可能不知道标签分隔的是什么,CSV等等,只是向他们展示预览。他们可以从选项中选择,直到输出看起来正确和表格。

然后你根据选择的格式解析它。

1

这不是一个完美的解决方案,但它可能会帮助你 - 如果你不能问分隔符是什么。

而不是试图解析为CSV,尝试只检索有效的电子邮件地址。我不认为空格,逗号,标签或换行符是否是有效的电子邮件部分? (谁知道;)查看关于using regular expressions to validate email的讨论 - 所以你可以看到这个解决方案的一些缺陷。

但是,我会使用preg_match_all()编写正则表达式,并以有效的电子邮件格式检索所有字符串的列表。

祝你好运!

0

这是我的解决方案。 它的作品,如果你知道你期望多少列。 最后,分隔符是在手动

actual_separation_character

$separator_1=","; 
$separator_2=";"; 
$separator_3="\t"; 
$separator_4=":"; 
$separator_5="|"; 

$separator_1_number=0; 
$separator_2_number=0; 
$separator_3_number=0; 
$separator_4_number=0; 
$separator_5_number=0; 

/* YOU NEED TO CHANGE THIS VARIABLE */ 
// Expected number of separation character (3 colums ==> 2 sepearation caharacter/row) 
$expected_separation_character_number=2; 


$file = fopen("upload/filename.csv","r"); 
while(! feof($file)) //read file rows 
{ 
    $row= fgets($file); 

    $row_1_replace=str_replace($separator_1,"",$row); 
    $row_1_length=strlen($row)-strlen($row_1_replace); 

    if(($row_1_length==$expected_separation_character_number)or($expected_separation_character_number==0)){ 
    $separator_1_number=$separator_1_number+$row_1_length; 
    } 

    $row_2_replace=str_replace($separator_2,"",$row); 
    $row_2_length=strlen($row)-strlen($row_2_replace); 

    if(($row_2_length==$expected_separation_character_number)or($expected_separation_character_number==0)){ 
    $separator_2_number=$separator_2_number+$row_2_length; 
    } 

    $row_3_replace=str_replace($separator_3,"",$row); 
    $row_3_length=strlen($row)-strlen($row_3_replace); 

    if(($row_3_length==$expected_separation_character_number)or($expected_separation_character_number==0)){ 
    $separator_3_number=$separator_3_number+$row_3_length; 
    } 

    $row_4_replace=str_replace($separator_4,"",$row); 
    $row_4_length=strlen($row)-strlen($row_4_replace); 

    if(($row_4_length==$expected_separation_character_number)or($expected_separation_character_number==0)){ 
    $separator_4_number=$separator_4_number+$row_4_length; 
    } 

    $row_5_replace=str_replace($separator_5,"",$row); 
    $row_5_length=strlen($row)-strlen($row_5_replace); 

    if(($row_5_length==$expected_separation_character_number)or($expected_separation_character_number==0)){ 
    $separator_5_number=$separator_5_number+$row_5_length; 
    } 

} // while(! feof($file)) END 
fclose($file); 

/* THE FILE ACTUAL SEPARATOR (delimiter) CHARACTER */ 
/* $actual_separation_character */ 

if ($separator_1_number==max($separator_1_number,$separator_2_number,$separator_3_number,$separator_4_number,$separator_5_number)){$actual_separation_character=$separator_1;} 
else if ($separator_2_number==max($separator_1_number,$separator_2_number,$separator_3_number,$separator_4_number,$separator_5_number)){$actual_separation_character=$separator_2;} 
else if ($separator_3_number==max($separator_1_number,$separator_2_number,$separator_3_number,$separator_4_number,$separator_5_number)){$actual_separation_character=$separator_3;} 
else if ($separator_4_number==max($separator_1_number,$separator_2_number,$separator_3_number,$separator_4_number,$separator_5_number)){$actual_separation_character=$separator_4;} 
else if ($separator_5_number==max($separator_1_number,$separator_2_number,$separator_3_number,$separator_4_number,$separator_5_number)){$actual_separation_character=$separator_5;} 
else {$actual_separation_character=";";} 

/* 
if the number of columns more than what you expect, do something ... 
*/ 

if ($expected_separation_character_number>0){ 
if ($separator_1_number==0 and $separator_2_number==0 and $separator_3_number==0 and $separator_4_number==0 and $separator_5_number==0){/* do something ! more columns than expected ! */} 
} 
1

SplFileObject::getCsvControl在$我没有发现它,直到为时已晚,所以写了效果很好的功能。 在情况下,它是有用/感兴趣我的做法是:

我用$handle$ColName参数与$ColName可选

$ COLNAME让你检查它的分隔符的第一个记录找到一个预期的标题列名,如果csv文件有一个标题行。

如果没有标题行,或者您不知道列名称,它将使用默认检查:哪个分隔符可找到同一记录的大多数字段(通常这是正确的)。然后,我还检查该分隔符是否会为接下来的几行返回相同数量的字段。

fgetcsv出现在块工作,并迫使每条记录有相同数量的该块中的最大领域,因此这将有不同的每个记录的字段数甚至工作