как узнать, являются ли поля файла csv табуляцией или запятыми

как узнать, являются ли поля файла csv табуляцией или разделителями с запятой. Для этого мне нужна проверка php. Может ли кто-нибудь помочь? Заранее спасибо.

Solutions Collecting From Web of "как узнать, являются ли поля файла csv табуляцией или запятыми"

Слишком поздно ответить на этот вопрос, но надеюсь, что это поможет кому-то.

Вот простая функция, которая вернет разделитель файла.

 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 

PS Я использовал preg_split () вместо explode (), потому что explode ('\ t', $ value) не даст правильных результатов.

UPDATE: Спасибо за @RichardEB, указав на ошибку в коде. Я обновил это сейчас.

Вот что я делаю.

  1. Разбор первых 5 строк файла CSV
  2. Подсчитайте количество разделителей [запятые, вкладки, точки с запятой и двоеточия] в каждой строке
  3. Сравните количество разделителей в каждой строке. Если вы правильно отформатировали 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]; 

Существует 100% надежный способ определить это. Что вы можете сделать, это

  • Если у вас есть способ проверки прочитанных полей, попробуйте прочитать несколько полей с использованием разделителя и подтвердить его. Если он сломается, используйте другой.
  • Подсчитайте появление вкладок или запятых в файле. Обычно один значительно выше, чем другой
  • И последнее, но не менее важное: спросите пользователя и позвольте ему переопределить ваши догадки.

В моей ситуации пользователи поставляют файлы csv, которые затем вводятся в базу данных SQL. Они могут сохранять электронную таблицу Excel как файлы с разделителями-запятыми или табуляторами. Программа, преобразующая таблицу в SQL, должна автоматически определять, будут ли поля разделены на вкладку или запятыми

Многие экспорт Excel csv имеют заголовки полей в качестве первой строки. Тест заголовка вряд ли будет содержать запятые, кроме как разделитель. Для моей ситуации я подсчитал запятые и вкладки первой строки и использовал это с большим числом, чтобы определить, является ли это csv или вкладкой

Я просто подсчитываю вхождения различных разделителей в 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]; 

Я использовал решение @Jay Bhatt для определения разделителя csv-файла, но для меня это не сработало, поэтому я применил несколько исправлений и комментариев, чтобы этот процесс был более понятным.

См. Мою версию функции @Jay Bhatt:

 function decide_csv_delimiter($file, $checkLines = 10) { // use php's 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.

Помимо тривиального ответа, что c sv-файлы всегда разделены запятой – это имя, я не думаю, что вы можете придумать какие-либо жесткие правила. Файлы TSV и CSV достаточно слабо определены, что вы можете найти файлы, которые были бы приемлемыми.

 A\tB,C 1,2\t3 

(Предполагая \ t == TAB)

Как бы вы определили, является ли это TSV или CSV?

Когда я вывожу 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 } ?> 

Я предполагаю, что это может быть неправильным, потому что у вас также могут быть вкладки и запятые в фактическом содержимом. Это просто идея. Использование регулярных выражений может быть лучше, хотя я не слишком об этом думаю.

Спасибо за все ваши входы, я сделал мои, используя ваши трюки: 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']; } 

Вы также можете использовать fgetcsv ( http://php.net/manual/en/function.fgetcsv.php ), передавая ему параметр разделителя. Если функция возвращает false, это означает, что параметр $ delimiter не был правильным

образец, чтобы проверить, является ли разделитель «;»

 if (($data = fgetcsv($your_csv_handler, 1000, ';')) !== false) { $csv_delimiter = ';'; } 

Как насчет чего-то простого?

 function findDelimiter($filePath, $limitLines = 5){ $file = new SplFileObject($filePath); $delims = $file->getCsvControl(); return $delims[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 ! */} } 

Если у вас очень большой пример файла в GB, запустите первую строку, поставьте временный файл. Открыть временный файл в vi

 head test.txt > te1 vi te1 

Самый простой способ ответить на это – открыть его в текстовом редакторе или в TextMate.