как узнать, являются ли поля файла csv табуляцией или разделителями с запятой. Для этого мне нужна проверка php. Может ли кто-нибудь помочь? Спасибо заранее.
Как узнать, являются ли поля файла csv табуляцией или запятыми
Ответ 1
Слишком поздно ответить на этот вопрос, но надеюсь, что это поможет кому-то.
Вот простая функция, которая вернет разделитель файла.
function getFileDelimiter($file, $checkLines = 2){
$file = new SplFileObject($file);
$delimiters = array(
',',
'\t',
';',
'|',
':'
);
$results = array();
$i = 0;
while($file->valid() && $i <= $checkLines){
$line = $file->fgets();
foreach ($delimiters as $delimiter){
$regExp = '/['.$delimiter.']/';
$fields = preg_split($regExp, $line);
if(count($fields) > 1){
if(!empty($results[$delimiter])){
$results[$delimiter]++;
} else {
$results[$delimiter] = 1;
}
}
}
$i++;
}
$results = array_keys($results, max($results));
return $results[0];
}
Используйте эту функцию, как показано ниже:
$delimiter = getFileDelimiter('abc.csv'); //Check 2 lines to determine the delimiter
$delimiter = getFileDelimiter('abc.csv', 5); //Check 5 lines to determine the delimiter
P.S Я использовал preg_split() вместо explode(), потому что explode ('\ t', $value) не даст правильных результатов.
UPDATE: Спасибо за @RichardEB, указав на ошибку в коде. Я обновил это сейчас.
Ответ 2
Вот что я делаю.
- Разбор первых 5 строк файла CSV
- Подсчитайте количество разделителей [запятые, вкладки, точки с запятой и двоеточия] в каждой строке
- Сравните количество разделителей в каждой строке. Если вы правильно отформатировали CSV, то в каждой строке будет соответствовать один из счетчиков разделителей.
Это не будет работать в 100% случаев, но это достойная отправная точка. Как минимум, это уменьшит количество возможных разделителей (облегчит пользователям выбор правильного разделителя).
/* Rearrange this array to change the search priority of delimiters */
$delimiters = array('tab' => "\t",
'comma' => ",",
'semicolon' => ";"
);
$handle = file( $file ); # Grabs the CSV file, loads into array
$line = array(); # Stores the count of delimiters in each row
$valid_delimiter = array(); # Stores Valid Delimiters
# Count the number of Delimiters in Each Row
for ( $i = 1; $i < 6; $i++ ){
foreach ( $delimiters as $key => $value ){
$line[$key][$i] = count( explode( $value, $handle[$i] ) ) - 1;
}
}
# Compare the Count of Delimiters in Each line
foreach ( $line as $delimiter => $count ){
# Check that the first two values are not 0
if ( $count[1] > 0 and $count[2] > 0 ){
$match = true;
$prev_value = '';
foreach ( $count as $value ){
if ( $prev_value != '' )
$match = ( $prev_value == $value and $match == true ) ? true : false;
$prev_value = $value;
}
} else {
$match = false;
}
if ( $match == true ) $valid_delimiter[] = $delimiter;
}//foreach
# Set Default delimiter to comma
$delimiter = ( $valid_delimiter[0] != '' ) ? $valid_delimiter[0] : "comma";
/* !!!! This is good enough for my needs since I have the priority set to "tab"
!!!! but you will want to have to user select from the delimiters in $valid_delimiter
!!!! if multiple dilimiter counts match
*/
# The Delimiter for the CSV
echo $delimiters[$delimiter];
Ответ 3
Существует 100% надежный способ определить это. Что вы можете сделать, это
- Если у вас есть метод проверки прочитанных полей, попробуйте прочитать несколько полей с помощью разделителя и проверить на свой метод. Если он сломается, используйте другой.
- Подсчитайте появление вкладок или запятых в файле. Обычно один из них значительно выше, чем другой.
- И последнее, но не менее важное: спросите пользователя и позвольте ему переопределить ваши догадки.
Ответ 4
В моей ситуации пользователи поставляют файлы csv, которые затем вводятся в базу данных SQL. Они могут сохранять электронную таблицу Excel как файлы с разделителями-запятыми или табуляторами. Программа, преобразующая таблицу в SQL, должна автоматически определять, будут ли поля разделены на вкладку или запятыми
Многие экспорт Excel csv содержат заголовки полей в качестве первой строки. Тест заголовка вряд ли будет содержать запятые, кроме как разделитель. Для моей ситуации я подсчитал запятые и вкладки первой строки и использовал это с большим числом, чтобы определить, является ли это csv или tab
Ответ 5
Я просто подсчитываю вхождения различных разделителей в CSV файл, тот, который, скорее всего, должен быть правильным разделителем:
//The delimiters array to look through
$delimiters = array(
'semicolon' => ";",
'tab' => "\t",
'comma' => ",",
);
//Load the csv file into a string
$csv = file_get_contents($file);
foreach ($delimiters as $key => $delim) {
$res[$key] = substr_count($csv, $delim);
}
//reverse sort the values, so the [0] element has the most occured delimiter
arsort($res);
reset($res);
$first_key = key($res);
return $delimiters[$first_key];
Ответ 6
Я использовал решение @Jay Bhatt для определения разделителя файлов csv, но для меня это не сработало, поэтому я применил несколько исправлений и комментариев, чтобы этот процесс был более понятным.
См. мою версию функции @Jay Bhatt:
function decide_csv_delimiter($file, $checkLines = 10) {
// use php built in file parser class for validating the csv or txt file
$file = new SplFileObject($file);
// array of predefined delimiters. Add any more delimiters if you wish
$delimiters = array(',', '\t', ';', '|', ':');
// store all the occurences of each delimiter in an associative array
$number_of_delimiter_occurences = array();
$results = array();
$i = 0; // using 'i' for counting the number of actual row parsed
while ($file->valid() && $i <= $checkLines) {
$line = $file->fgets();
foreach ($delimiters as $idx => $delimiter){
$regExp = '/['.$delimiter.']/';
$fields = preg_split($regExp, $line);
// construct the array with all the keys as the delimiters
// and the values as the number of delimiter occurences
$number_of_delimiter_occurences[$delimiter] = count($fields);
}
$i++;
}
// get key of the largest value from the array (comapring only the array values)
// in our case, the array keys are the delimiters
$results = array_keys($number_of_delimiter_occurences, max($number_of_delimiter_occurences));
// in case the delimiter happens to be a 'tab' character ('\t'), return it in double quotes
// otherwise when using as delimiter it will give an error,
// because it is not recognised as a special character for 'tab' key,
// it shows up like a simple string composed of '\' and 't' characters, which is not accepted when parsing csv files
return $results[0] == '\t' ? "\t" : $results[0];
}
Я лично использую эту функцию для автоматического анализа файла с помощью PHPExcel, и он работает красиво и быстро.
Я рекомендую разбор не менее 10 строк, чтобы результаты были более точными. Я лично использую его со 100 линиями, и он работает быстро, без задержек или задержек. Чем больше линий вы разбираете, тем точнее результат.
ПРИМЕЧАНИЕ. Это просто модифицированная версия решения @Jay Bhatt. Все кредиты принадлежат @Jay Bhatt.
Ответ 7
Помимо тривиального ответа, что файлы c sv всегда разделяются запятыми - это имя, я не думаю, что вы можете придумать какие-либо жесткие правила. Файлы TSV и CSV достаточно слабо определены, что вы можете найти файлы, которые были бы приемлемыми.
A\tB,C
1,2\t3
(Предполагая\t == TAB)
Как бы вы определили, является ли это TSV или CSV?
Ответ 8
Когда я вывожу файл TSV, я создаю вкладки, используя \t тот же самый метод, который будет писать разрыв строки, такой как \n, так что, как я уже сказал, метод может быть следующим:
<?php
$mysource = YOUR SOURCE HERE, file_get_contents() OR HOWEVER YOU WISH TO GET THE SOURCE;
if(strpos($mysource, "\t") > 0){
//We have a tab separator
}else{
// it might be CSV
}
?>
Я предполагаю, что это может быть не так, потому что у вас также есть вкладки и запятые в фактическом содержимом. Это просто идея. Использование регулярных выражений может быть лучше, хотя я не слишком смущен этим.
Ответ 9
Спасибо за все ваши входы, я сделал свои твои трюки: preg_split, fgetcsv, loop и т.д.
Но я реализовал то, что было удивительно не здесь, использование fgets вместо чтения всего файла, лучше, если файл тяжелый!
Здесь код:
ini_set("auto_detect_line_endings", true);
function guessCsvDelimiter($filePath, $limitLines = 5) {
if (!is_readable($filePath) || !is_file($filePath)) {
return false;
}
$delimiters = array(
'tab' => "\t",
'comma' => ",",
'semicolon' => ";"
);
$fp = fopen($filePath, 'r', false);
$lineResults = array(
'tab' => array(),
'comma' => array(),
'semicolon' => array()
);
$lineIndex = 0;
while (!feof($fp)) {
$line = fgets($fp);
foreach ($delimiters as $key=>$delimiter) {
$lineResults[$key][$lineIndex] = count (fgetcsv($fp, 1024, $delimiter)) - 1;
}
$lineIndex++;
if ($lineIndex > $limitLines) break;
}
fclose($fp);
// Calculating average
foreach ($lineResults as $key=>$entry) {
$lineResults[$key] = array_sum($entry)/count($entry);
}
arsort($lineResults);
reset($lineResults);
return ($lineResults[0] !== $lineResults[1]) ? $delimiters[key($lineResults)] : $delimiters['comma'];
}
Ответ 10
Вы также можете использовать fgetcsv (http://php.net/manual/en/function.fgetcsv.php), передавая ему параметр разделителя. Если функция возвращает false, это означает, что параметр $delimiter не был правильным.
чтобы проверить, равен ли разделитель ';'
if (($data = fgetcsv($your_csv_handler, 1000, ';')) !== false) { $csv_delimiter = ';'; }
Ответ 11
Как насчет чего-то простого?
function findDelimiter($filePath, $limitLines = 5){
$file = new SplFileObject($filePath);
$delims = $file->getCsvControl();
return $delims[0];
}
Ответ 12
Это мое решение. Его работы, если вы знаете, сколько столбцов вы ожидаете. Наконец, разделительный символ - это $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 ! */}
}
Ответ 13
Если у вас очень большой пример файла в GB, запустите первую строку, поставьте временный файл. Откройте временный файл в vi
head test.txt > te1
vi te1
Ответ 14
Самый простой способ ответить на это - открыть его в текстовом редакторе или в TextMate.