使用分隔符数组

5
我将使用fgetcsv来读取我的应用程序中的csv文件。问题是我不知道我的用户会使用哪种分隔符,例如,, |, 或者;。如果我什么也不告诉fgetcsv,它只会接受,作为分隔符,但如果我告诉它使用特定的分隔符,它将只接受该分隔符。
现在我正在做的是:
while (($row = fgetcsv($fileHandle, 4096)) !== false) { 

我希望你能够提供以下内容:那就是类似这样的东西:
while (($row = fgetcsv($fileHandle, 4096, array(',', ';', '|'))) !== false) {

有没有一些简单的方法可以实现这个功能?因为CSV并没有标准化,所以你不应该被限制在某一个特定字符上。


1
我认为你会遇到类似这个问题:https://dev59.com/fHA75IYBdhLWcg3wP2kg <- 因为如果你的 CSV 文件中有逗号和分号,你会选择哪一个作为分隔符呢? - Rizier123
你的问题与标签所示的Laravel无关。 - Emeka Mbah
@Rizier123 CSV文件中只包含电子邮件地址和两个字母。因此,我知道任何逗号、竖线或分号都是分隔符。 - Christoffer
2
你可能会对电子邮件地址中实际允许的字符感到惊讶... 电子邮件地址的本地部分可以使用以下任何ASCII字符RFC 5322第3.2.3节: 字母(a-z,A-Z) 数字0到9 Chars!#$%&'*+-/ =?^_`{|}〜 字符。 (点,句号,句号),前提是它不是第一个或最后一个字符,并且还要求它不连续出现两次或更多次。 特殊字符允许但有限制: 空格和“(),:;<> @ []” 包含在引号中,并且空格,反斜杠\和引号“”也必须由反斜杠\前缀。 - Gavin Jackson
它没有被标准化,但在单个CSV文件中只能有一个。如何扫描每个文件并计算分隔符出现的次数? - MeanGreen
3个回答

6

如果您不知道csv文件的分隔符,那么您无法可靠地确定它。看一个简单的例子:

foo;bar,hello;world

什么是分隔符?是 , 还是 ;?如果你传递一个数组 array(',',';'),你期望 fgetcsv() 返回什么数据?
如果你不知道分隔符,需要向用户询问。

3
那么它就不再是CSV格式了。CSV只支持单个分隔符。为什么不在解析之前用逗号替换分号呢?除非你有一个非常大的输入文件,否则这种做法或许是可行的。 - hek2mgl
1
@hek2mgl 我正在考虑按照你所说的替换字符。这可能是最好的解决方案。第二好的解决方案可能是要求用户输入分隔符。 - Christoffer
1
@Christoffer 是的,你最后的评论是正确的!+1 :) - hek2mgl
1
顺便说一下,其实并没有CSV标准...(我之前用过这个词,但是不正确)...更确切地说,CSV只是一种默契的协议,而且有很多变体。 - hek2mgl
1
@hek2mgl 是的,缺乏标准是一个问题。再加上微软不允许用户在将 Excel 文件保存为 CSV 时自行选择分隔符(需要更改系统区域设置)。因此,你无法告诉新手用户应该使用哪个分隔符,因为对于他们来说,仅仅是更改保存格式已经很困难了。 - Christoffer
显示剩余9条评论

1
使用league/csv包,它具有检测功能和更多功能,使其值得使用而不是fgetcsv。

基本上,这是一个所谓的“仅链接答案”。但我还需要强调的是,当然,那个库也不接受分隔符数组。 - hek2mgl

0

仅为任何其他遇到此问题的人提供简单的答案。我采取的解决方案是将所有分隔符替换为一个特定的字符。 像这样:

private function replaceDelimiters($file)
{
    // Delimiters to be replaced: pipe, comma, semicolon, caret, tabs
    $delimiters = array('|', ';', '^', "\t");
    $delimiter = ',';

    $str = file_get_contents($file);
    $str = str_replace($delimiters, $delimiter, $str);
    file_put_contents($file, $str);
}

请注意,这将把所有给定的字符替换为“,”。因此,只有在您知道这些字符仅用作分隔符而不是内容时,这才是一个好选择(就像我的情况一样)。
此外,我还写了一篇博客文章

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接