在分隔符(;)和分隔符(,)上爆炸csv文件?

时间:2015-05-27 08:22:29

标签: php codeigniter csv

当我在分隔符(;)上爆炸csv文件时 在一些excel程序中成功爆发而在其他程序中失败

当我在分隔符(,)上爆炸csv文件时 在一些excel程序中成功爆发而在其他程序中失败

如何在所有版本的Excel中进行爆炸? 我怎么知道爆炸的完美分隔符?

是的,有代码..

if (!function_exists('create_csv')) {
    function create_csv($query, &$filename = false, $old_csv = false) {
        if(!$filename) $filename = "data_export_".date("Y-m-d").".csv";
        $ci = &get_instance();
        $ci->load->helper('download');
        $ci->load->dbutil();
        $delimiter = ";";
        $newline = "\r\n";
        $csv = "Data:".date("Y-m-d").$newline;
        if($old_csv)
            $csv .= $old_csv;
        else
            $csv .= $ci->dbutil->csv_from_result($query, $delimiter, $newline);
        $columns = explode($newline, $csv);
        $titles = explode($delimiter, $columns[1]);
        $new_titles = array();
        foreach ($titles as $item) {
            array_push($new_titles, lang(trim($item,'"')));
        }
        $columns[1] = implode($delimiter, $new_titles);
        $csv = implode($newline, $columns);
        return $csv;
    }
}

有时候我把$ delimiter =“;”; 和某些受害者$ delimiter =“,”;

感谢..

5 个答案:

答案 0 :(得分:1)

如果您对预期数据(列数)有所了解,那么这可能是一个很好的猜测,并且可能是比较哪种情况发生的最佳选择(取决于您期望的数据类型) 。 如果你有一个标题记录,我会想象它会更好。 (您可以检查特定的标头值)

很抱歉不适合你的代码,但我不确定你正在做什么电话,但你应该能够适应它。

$expected_num_of_columns = 10;
$delimiter = "";

foreach (array(",", ";") as $test_delimiter) {
   $fid = fopen ($filename, "r");
   $csv_row = fgetcsv($fid, 0, $test_delimiter);
   if (count($csv_row) == $expected_num_of_columns) {
       $delimiter = $test_delimiter;
       break;
   }
   fclose($fid);
}

if (empty($delimiter)) {
   die ("Input file did not contain the correct number of fields (" . $expected_num_of_columns . ")");  
}

例如,如果所有或大多数字段都包含非整数(例如货币金额列表)且没有标题记录,请不要使用此项,因为;分隔的文件很可能使用,作为小数点,可以使用相同数量的逗号和分号。

答案 1 :(得分:1)

您可以使用辅助函数来检测最佳分隔符,如:

public function find_delimiter($csv)
{
    $delimiters = array(',', '.', ';');
    $bestDelimiter = false;
    $count = 0;
    foreach ($delimiters as $delimiter)
        if (substr_count($csv, $delimiter) > $count) {
            $count = substr_count($csv, $delimiter);
            $bestDelimiter = $delimiter;
        }
    return $bestDelimiter;
}

答案 2 :(得分:0)

无法100%确定您的目标是真正的分隔符。你所能做的只是猜测。

您应首先找到正确的分隔符,然后在此分隔符上展开CSV。

要找到分隔符,基本上,您需要一个计算,的数量和;的数量的函数,并返回更大的值。

类似的东西:

$array = explode(find_delimiter($csv), $csv);

希望它有所帮助;)

编辑:您的find_delimiter功能可能类似于:

function find_delimiter($csv)
{
   $arrDelimiters = array(',', '.', ';');
   $arrResults = array();
   foreach ($arrDelimiters as $delimiter)
   {
       $arrResults[$delimiter] = count(explode($delimiter, $csv));
   }
   $arrResults = rsort($arrResults);
   return (array_keys($arrResults)[0]);
}

答案 3 :(得分:0)

简短的回答是,除非您可以应用一些启发式方法来确定文件格式,否则您可能无法做到。如果您不知道并且无法检测到您正在解析的文件的格式,那么解析它将很困难。

但是,一旦确定(或需要特定的)分隔符格式。您可能会发现php的内置fgetcsv比基于手动explode的策略更容易,更准确。

答案 4 :(得分:0)

好吧,看起来您确切知道您的分隔符将是“,”或“;”。这是一个很好的起点。因此,您可以尝试将所有逗号(,)替换为分号(;),然后仅使用分号进行分解。但是,在这种方法中,在某些情况下肯定会出现问题,因为CSV文件的某些行可能是这样的:

  

“名称,值”,其他名称,其他值,姓氏;最后一个值

这样,如果CSV文件中有四列,则CSV文件的分隔符将为逗号。但是,通过将逗号更改为分号,您将获得五列不正确的列。因此,将一些分隔符更改为另一个分隔符并不是一个好方法。

但是,如果您的CSV文件格式正确,那么您可以在任何行中找到正确的分隔符。因此,您可以尝试创建一些像@johnkork所提议的函数,如find_delimiter($ csvLine),但问题是函数本身无法知道要搜索哪个分隔符。但是,您确切地知道所有可能的分隔符,因此您可能会尝试创建另一个非常相似的函数,如delimiter_exists($ csvLine,$ delimiter),它返回true或false。

但即使是函数delimiter_exists($ csvLine,$ delimiter)也不够。为什么?因为对于上面提供的CSV行的实例,你会得到“,”和“;”是存在的分隔符。对于逗号,它将是包含四列的CSV文件,对于分号,它将是两列。

因此,没有通用的方法可以让你得到你想要的。但是,可能还有另一种方法可以检查 - CSV文件的第一行是标题,假设您的CSV文件有标题。大多数情况下,CSV文件中的标题(不一定)没有其他符号,除了列的字母数字名称,由特定的分隔符分隔。因此,您可以尝试创建像delimiter_exists($ csvHeader,$ delimiter)这样的函数,其实现可能是这样的:

function delimiter_exists($csvHeader, $delimiter) {
    return (bool)preg_match("/$delimiter/", $csvHeader);
}

对于您的具体情况,您可以像这样使用它:

$csvHeader = "abc;def";
$delimiter = delimiter_exists($csvHeader, ',') ? ',' : ';';

希望这有帮助!