Подтвердить что ты не робот

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

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

4b9b3361

Ответ 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.