3

I want open a file CSV with php but the input can be with comma or semicolon how i can do that

i open the file with comma like that

if (($handle = fopen($filePath, 'r')) !== false) {
    // get the first row, which contains the column-titles (if necessary)
    $header = fgetcsv($handle);
      while (($data = fgetcsv($handle)) !== false) {
        var_dump($data);
      }
}

my file can be

   Test;option;money
   1;a;1,3
   2;"G;a";1,965,0

OR

   Test,option,money
   1,a,"1,3"
   2,"G;a",1,"965,0"

how i can test the separator to use fgetcsv ?

Guilherme Freire
  • 372
  • 5
  • 17
  • You can use the 3rd parameter of [`fgetcsv()`](http://php.net/manual/en/function.fgetcsv.php) to specify a different separator, but you can only specify *one* at a time. – Sammitch Dec 20 '16 at 17:59
  • php's built in csv functions only support one delimeter at a time. – Jonathan Kuhn Dec 20 '16 at 17:59
  • 1
    So what you do is read a line using comma as delimiter, and count how many elements are in the array. If only one, then close the file handle, reopen, etc. and read using semicolon as delimiter. – ivanivan Dec 20 '16 at 18:04
  • how i can test the file to use just right delimeter – Guilherme Freire Dec 20 '16 at 18:04
  • [Maybe you'll find the answer in this StackOverflow article. There's an implementation proposal of a getFileDelimiter function.](http://stackoverflow.com/questions/3395267/how-to-find-out-if-csv-file-fields-are-tab-delimited-or-comma-delimited) – actc Dec 20 '16 at 18:10

3 Answers3

8

Maybe you can find the answer in this StackOverflow article. It proposes an implementation for a delimiter detection method. The implementation is:

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];
    }

Using that method you might end up with:

$delimiter = getFileDelimiter($filePath); // actual path of the file, ex: '../example.csv'

if (($handle = fopen($filePath, 'r')) !== false) {
    // get the first row, which contains the column-titles (if necessary)
    $header = fgetcsv($handle, 0, $delimiter);
      while (($data = fgetcsv($handle)) !== false) {
        var_dump($data);
      }
}
actc
  • 672
  • 1
  • 9
  • 23
1

If the semi-colon and comma are used interchangeably, you would have to read the file in using one delimiter and then loop over each "column" and run that through str_getcsv to parse with the second delimeter. Something like this:

if (($handle = fopen($filePath, 'r')) !== false) {
    // get the first row, which contains the column-titles (if necessary)
    $header = fgetcsv($handle);
    while (($data = fgetcsv($handle)) !== false) {
        //create empty array for this line
        $line = array();
        //loop over each "column" read in
        foreach($data as $d){
            //split using second delimeter and merge with line data
            $line = array_merge($line, str_getcsv($d, ';'));
        }
        //display the line
        print_r($line);
    }
}

Other than that, you would have to make/find your own csv parser that supports multiple delimeters.

Jonathan Kuhn
  • 15,279
  • 3
  • 32
  • 43
0

You can try this:

<?php
if (($handle = fopen($filePath, 'r')) !== false) {
    // Detect delimiter from first line.
    $delimiter = null;
    if ($firstLine = fgets($handle) !== false) {        
        if (strpos($firstLine, ",") !== false) {
            $delimiter = ",";
        } elseif (strpos($firstLine, ";") !== false) {
            $delimiter = ";"
        }
    }

    if (!is_null($delimiter)) {
        $isHeader = true;
        while (($data = fgetcsv($handle, 0, $delimiter)) !== false) {
            if ($isHeader) {
                $isHeader = false;
                continue;
            }

            var_dump($data);
        }
    }
}

First try to detect delimiter from first line and than use it in parsing csv file.

  • What about this case: `Text Column1 ; 43,78 ; Text Column3`? Your code detects one comma and thinks the delimiter is a comma but is the semicolon. – Tomás Oct 14 '21 at 22:20