Verhextes CSV mit PHP entzaubert

Fast jeder Entwickler kennt das. "Die Daten erhalten Sie als CSV ....".
Diese Informationen müssen reichen. Wie bekommt man nun heraus, welche Separatoren verwendet werden?
Mit dem hier veröffentlichten PHP-Skript kein Problem.

Sicher hatten Sie auch schon einmal das Problem, CSV Dateien mit unbekannten Format, mittels PHP verarbeiten zu müßen.
Eigentlich kein Problem, oder? Nur was ist, wenn Ihnen unbekannt ist, welche Art von Separator für die Spalten verwendet wird?
Oder noch schlimmer, dieser sich immer wieder ändern kann.

Dieses Problem hatten wir auch und enwickelten deshalb die CSV Analyse Klasse.
So können CSV-Dateien aus verschiedensten Quellen eingelesen und ausgewertet werden - ohne das der Separator bekannt ist.

PHP Example

<?PHP

class CSV_Analyze
{
  function find_separator($set)
  {
     $squode = FALSE;
     $quode  = FALSE;
     $bslash = FALSE;
     if (!$set) return False;
     for ($i = 0; $i <= strlen($set); $i++)
     {
        switch (TRUE)
        {
          case substr($set, $i, 1) == '\':
            if ($bslash == FALSE)
              $bslash = $i;  //bslash setzen
          break;
          case substr($set, $i, 1) == '"':
            if ($quote && !$bslash)
                 $quote  = FALSE;  //quote setzen
            elseif (!$squote)
                 $quote  = TRUE;  //quote setzen
          break;
          case substr($set, $i, 1) == '\'':
            if ($squote && !$bslash)
                 $squote  = FALSE;  //quote setzen
            elseif (!$quote)
                 $squote  = TRUE;  //quote setzen
          break;
        }
        #wenn kein squote oder quote aktiv und kein standard zeichen
        if (!$squote && !$quote && !preg_match("=[a-zA-Z0-9_\-\+\"\']{1}=", substr($set, $i, 1)))
          $possible[ord(substr($set, $i, 1))]++;
     }
     # sortiere nach Anzahl
     arsort ($possible);
     $array = each($possible);
     RETURN chr($array[0]);
  }
  function split_in_rows($set, $separator = ";")
  {
     if (!$set) return False;
     $squode = FALSE;
     $quode  = FALSE;
     $bslash = FALSE;
     $temp = "";
     $laststart = 0;
     for ($i = 0; $i <= strlen($set); $i++)
     {
        switch (TRUE)
        {
          case substr($set, $i, 1) == '\':
            if ($bslash == FALSE)
              $bslash = $i;  //bslash setzen
          break;
          case substr($set, $i, 1) == '"':
            if ($quote && !$bslash)
                 $quote  = FALSE;  //quote setzen
            elseif (!$squote)
                 $quote  = TRUE;  //quote setzen
          break;
          case substr($set, $i, 1) == '\'':
            if ($squote && !$bslash)
                 $squote  = FALSE;  //quote setzen
            elseif (!$quote)
                 $squote  = TRUE;  //quote setzen
          break;
        }
        #wenn kein squote oder quote aktiv und kein standard zeichen
        if ($squote || $quote || substr($set, $i, 1) != $separator) continue;
        $val = preg_replace("=^[\"']=", "" ,trim(substr($set, $laststart, $i - $laststart)));
        $temp[] = preg_replace("=[\"']$=", "" ,$val);
        $laststart = $i + 1;
   }
     # am Ende Angekommen, noch den Rest anhängen
     $val = preg_replace("=^[\"']=", "" ,trim(substr($set, $laststart, strlen($set) - $laststart)));
     $temp[] = preg_replace("=[\"']$=", "" ,$val);
     return $temp;
     #return split ( $separator, $set);
  }
}


  # importfile einlesen
  $file = file("csvtest.csv");
  $CSV = new CSV_Analyze();
  # analysiert die erste Zeile und liefert den Separator zurück
  $separator = $CSV->find_separator($file[0]);
  # in die Spalten zerlegen
  $set = "<table width='100%' border='1'>";
  for ($i = 0; $i <= count($file); $i++)
  {
    # liefert eine Zeile zerlegt in Spalten zurück
    $array = $CSV->split_in_rows($file[$i], $separator);
    if ($array)
    {
      $set .= "<tr>";
      foreach ($array as $v)
      {
        $set .= "<td>".$v."</td>";
      }
      $set .= "</tr>";
    }
  }
  $set .= "</table>";
  echo $set;

?>

Diese Klasse können Sie gern verwenden und bei Bedarf umschreiben oder erweitern.
Ich würde mich freuen Ihre Verbesserungen hier vorzustellen.

Mit freundlichen Grüßen
S.Ruttloff