Zend FR

Consultez la FAQ sur le ZF avant de poster une question

Vous n'êtes pas identifié.

#1 24-01-2008 13:18:18

sekaijin
Membre
Date d'inscription: 17-08-2007
Messages: 1137

Fast_Csv_Parser

Bonjour,
je vous livre ma classe csv parser
que j'ai écrit pour gérer correctement les fichier csv contenant des CRLF ou LF dans les champs.

elle s'appelle Fast non parce qu'elle est rapide mais parce qu'elle fait partie de ma librairie de classe de mise en œuvre rapide de ZF

Code:

<pre><?php

class Fast_Csv_Parser {
   /**
    * @param string $filename nom du fichier à parser
    * @param string $separator column separator char
    * @param string $enclosure column enclosure char
    */
   public function __construct($filename, $separator = ';',$enclosure='"') {
      $this->separator =$separator;
      $this->enclosure =$enclosure;
      $this->filename = $filename;
      $this->resource = fopen($filename,'r');
   }

   // replace double enclosure mark by single enclosure mark
   function cleanField($field) {
      return preg_replace('/'.$this->enclosure.$this->enclosure.'/', $this->enclosure, $field);
   }

   // Verify if is not truncated field
   function isCompletField(&$field) {
      if (($this->enclosure == substr($field, 0, 1)) &&
          ($this->enclosure == substr($field, -1, 1)) &&
          (0 == substr_count($field, $this->enclosure)%2))
      {
         $field = substr($field, 1, -1);
      }
      return (0 == substr_count($field, $this->enclosure)%2); //nombre pair de $this->enclosure
   }

   // get next row in cvs file
   public function getRow() {
      $line = $this->getLine();
      if (null != $line) {
         $this->row = array();
         $complete = false;
         $incompletField = false;
         //while incomplet row and not eof
         while (!$complete && null != $line) { 
            $list = explode ($this->separator, $line);
            foreach ($list as $key=>$value) {
               $value = trim($value,"\r\n");
               // if have an incomplet fiel try to complet it
               if ($incompletField) {
                  $value = $incompletField . $break . $value; 
               }
               if ($this->isCompletField($value)) //nombre pair de $this->enclosure
               {
                  $complete = ($key == count($list)-1); 
                  $this->row[] = $this->cleanField($value);
                  $incompletField = false;
               } else {
                  $incompletField = $value;
                  $break = $this->separator;
               }
            }
            if (!$complete && ($key == count($list)-1)) {
               $line = $this->getLine();
               $break = "\n";
            }      
         }
      } else {
         $this->row = null;
      
      }
      return $this->row;
   }

   // is end of file ?
   public function eof()
   {
      return (null === $this->row);
   }

   // close cvs file
   public function close () {
      if ($this->resource) {
         fclose($this->resource);
      }
   }

   public function getLine() {
      $line = null;
      if ($this->resource) {
         $line = fgets($this->resource);
      }
      return $line;
   }
}



$cvs = new Fast_Csv_Parser('csv.csv');
$row = $cvs->getRow();
while (!$cvs->eof()) {
   print_r($row);
   $row = $cvs->getRow();
}
$cvs->close();

si vous l'utilisez trouvez des bugs ou l'améliorez pensez à nous tous.
A+JYT

Dernière modification par sekaijin (24-01-2008 13:31:36)

Hors ligne

 

#2 25-01-2008 23:12:19

Phoenix17
Membre
Lieu: Nancy
Date d'inscription: 09-04-2007
Messages: 73
Site web

Re: Fast_Csv_Parser

Bonjour,

Code:

$this->resource = fopen($filename,'r');

Pourquoi ne pas utiliser file_get_content() tout simplement ? Ca t'éviterai de devoir fermer avec $cvs->close();

Simon

Hors ligne

 

#3 26-01-2008 00:13:13

Mr.MoOx
Administrateur
Lieu: Toulouse
Date d'inscription: 27-03-2007
Messages: 1444
Site web

Re: Fast_Csv_Parser

Ca doit surement être plus lourd en terme de perfs...
file_gets_content utilise peut être fopen et fclose smile

Hors ligne

 

#4 26-01-2008 02:45:31

Phoenix17
Membre
Lieu: Nancy
Date d'inscription: 09-04-2007
Messages: 73
Site web

Re: Fast_Csv_Parser

Bun oui c'est le but : file_get_contents regroupe fopen et fclose.

C'est plus pratique dans ce cas là : on est plus obliger de devoir fermer avec $cvs->close().

Hors ligne

 

#5 26-01-2008 10:40:19

sekaijin
Membre
Date d'inscription: 17-08-2007
Messages: 1137

Re: Fast_Csv_Parser

oui mais dans ce cas tu est ensuite obligé de faire un while avec sGets pour parser les lignes de ton buffer
le but n'est pas de mettre le texte du fichier dans un buffer mais de récupérer des enregistrement avec tous leurs champs
il y a pour ça fGetCsv mais cette fonction ne gère pas bien toutes les subtilités du format entre autre lorsque un champ contient dans ça valeur une ou plusieurs fois de séparateur. ou encore des " ou même des CRLF ou LF
comme ceci

Code:

a;b;c""d,"e;f";"g
h";i

ceci est une seule ligne de csv

Code:

array (
   [0] =>a
   [1] =>b
   [3] =>c"d
   [4] =>e;f
   [5] =>g
h
   [6] =>i
)

la fonction fGetCsv ne tient pas compte de toutes ces possibilités
et le file_get_contents remontre en mémoire tout le fichier sous forme d'une seule chaîne.

cela peut être intéressant parfois mais que sur de petit CSV de quelques centaines de colonnes et quelques millier de lignes
mais ça ne marche plus quand comme moi tu as à traiter des CSV donc chaque ligne pèse quelques kilos et que tu dois traiter quelques million de lignes

bref comme toujours les fonctions doivent faire un choix entre perf et resource (ici mémoire)
soit tu minimise l'un au profit de l'autre soit le contraire

on pourrait imaginer améliorer cette classe en faisant un file_size et en fonction de celui-ci utiliser un file_get_content et ensuite parser le buffer ou utiliser un fgets

A+JYT

Dernière modification par sekaijin (26-01-2008 10:41:24)

Hors ligne

 

Pied de page des forums

Propulsé par PunBB
© Copyright 2002–2005 Rickard Andersson
Traduction par punbb.fr

Graphisme réalisé par l'agence Rodolphe Eveilleau
Développement par Kitpages