当我在分隔符(;)上爆炸csv文件时在一些excel程序中爆炸成功,而在另一些程序中失败
也是当我在分隔符(,)上爆炸csv文件时在一些excel程序中爆炸成功,而在另一些程序中失败
如何在所有版本的excel中爆炸?我怎样才能知道最佳的分隔符是什么?
yes there is code.
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 = ",";
谢谢. .
您可以使用辅助函数来检测最佳分隔符,如:
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;
}
如果您知道期望的数据(列数),那么这可能是一个很好的猜测,并且可能是比较哪个出现最多的一个很好的替代方法(取决于您期望的数据类型)。我想,如果你有一个头记录,它会工作得更好。(您可以为特定的头值添加检查)
很抱歉没有把它放进你的代码中,但我真的不确定你在做什么调用,但你应该能够适应它。
$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 . ")");
}
不要使用这个,例如,如果所有或大部分字段包含非整数(例如货币金额列表)并且没有头记录,因为用;
分隔的文件最有可能使用,
作为小数点,并且可能有相同数量的逗号和分号。
简短的回答是,除非您可以应用一些启发式方法来确定文件格式,否则可能不能。如果你不知道也不能检测你正在解析的文件的格式,那么解析它将会很困难。
但是,一旦确定了(或需要特定的)分隔符格式。您可能会发现php内置的fgetcsv
将比手动基于explode
的策略更容易和更准确。
没有办法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]);
}
嗯,看起来您完全知道您的分隔符将是","或";"。这是一个很好的开始。因此,您可以尝试将所有逗号(,)替换为分号(;),然后仅以分号展开。但是,这种方法在某些情况下肯定会出现问题,因为CSV文件的某些行可能像这样:
"name,value",其他名称,其他值,姓;最后值
这样,如果您的CSV文件中有四列,则CSV文件的分隔符将是逗号。但是,通过将逗号更改为分号,您将得到五列,这将是不正确的。因此,将一些分隔符更改为另一个分隔符并不是一个好方法。
但是,如果您的CSV文件格式正确,那么您可能会在任何行中找到正确的分隔符。因此,您可以尝试创建一些函数,如@johnkork提出的find_delimiter($csvLine),但这样做的问题是,函数本身不知道要搜索哪个分隔符。但是,您确切地知道所有可能的分隔符,因此您可以尝试创建另一个非常类似的函数,如delimiter_exists($csvLine, $delimiter),该函数返回true或false。
但是,即使函数delimiter_exists($csvLine, $delimiter)也是不够的。为什么?因为对于上面提供的CSV行实例,您将得到","answers";"都是存在的分隔符。对于逗号,它将包含四列的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, ',') ? ',' : ';';
希望这对你有帮助!