Consultez la FAQ sur le ZF avant de poster une question
Vous n'êtes pas identifié.
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
<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
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
a;b;c""d,"e;f";"g h";i
ceci est une seule ligne de csv
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