Les fichiers au format CSV
Le format de fichier CSV ("Comma Separated Values") sert à échanger des données entre différentes applications et à sauvegarder des données. Les avantages de ce format de données sont d'utiliser une faible bande passante et peu d'espace de stockage.
Format des données
- Chaque fiche est sur une ligne - Le séparateur de ligne peut être LF (0x0A) ou CRLF (0x0D0A). Un séparateur de ligne peut aussi être encapsulé dans les données, la fiche étant alors sur plusieurs lignes.
- Virgules dans un champ - Le champ doit être délimité par des guillements.
- Guillements dans un champ - Les guillemets doivent être doublés et le champ doit être délimité par des guillemets.
- Séparateur de ligne dans un champ - Le champ doit être délimité par des guillements.
- Les champs délimités - Tous les champs peuvent être délimités par des guillemets, ces guillemets étant toujours ignorés de même que les espaces éventuels encadrants ces guillements.
- Les espaces de début et de fin sont conservés - sauf si l'on demande au logiciel de les supprimer.
Autrement dit:
- Un champ délimité par des guillements et incluant le séparateur, est traité comme un champ unique dont le séparateur fait partie.
- Les guillemets utilisés pour délimiter un champ sont ignorés.
- Des guillemets doubles dans un champ délimité par des guillemets, sont traités comme des guillemets simples.
- Un champ délimité par des guillemets peut contenir plusieurs lignes.
Particularités d'excel
- Excel utilise le séparateur de liste local comme séparateur des champs, soit la virgule aux USA et le point-virgule en Europe.
- Excel encode les caractères selon le système d'encodage du système d'exploitation, heureusement très proche du standard iso-8859-15 que l'on peut utiliser sans problème.
- Excel utilise \r\n comme caractère de fin de ligne.
- Excel supprime les espaces à gauche et à droite, ainsi que les zéros non-significatifs donc par exemples les zéros à gauche d'un numéro de téléphone.
Types Mime
On peut utiliser
- application/octet-stream
- text/comma-separated-values
- text/csv
Exemples
colonne A,colonne B,colonne C "Il a dit ""coucou !"" hier.","Hé, Je contiens une virgule !",125
Séparation des champs d'une ligne CSV vers un tableau à 1 dimension
En javascript
La fonction javascript suivante retourne un tableau contenant les différents champs d'une ligne CSV correspondant à une fiche. On assume que la ligne ne contient pas de r
String.prototype.splitCSV = function(sep , trim) { sep = sep || ","; if (!trim && this.indexOf('"') < 0) return this.split(sep); var elts = this.split(sep), elt = '', out = [], nq, i, j; for (i = 0; i < elts.length ; i++) { if (elt =='') elt = elts[i]; else elt += sep + elts[i]; nq = elt.length - elt.replace(/"/g , '').length; if (nq % 2 == 0) { if (nq > 0) { elt = elt.replace(/^\s+|\s+$/g,""); //Supprime les espaces encadrant les " qui limitent les éléments de la chaîne j = elt.indexOf('"'); elt = elt.substring(0,j) + elt.substring(j+1); j = elt.lastIndexOf('"'); elt = elt.substring(0,j) + elt.substring(j+1); elt = elt.replace(/""/g , '"') } if (trim) out.push(elt.replace(/^\s+|\s+$/g,"")); else out.push(elt); elt = ''; } } if (elt == '') return out; else return false; //La chaine contient un \n, à combiner avec la chaine suivante }
En php
La même fonction en php, toujours en assumant que la ligne ne contient pas de r
function splitCSV($string, $sep="," , $trim = false) { if (!$trim && strpos($string , '"') === false) return explode($sep, $string); $elts = explode($sep, $string); $elt = ''; $out = array(); for ($i = 0; $i < count($elts); $i++) { if ($elt == '') $elt = $elts[$i]; else $elt .= $sep . $elts[$i]; $nq = substr_count($elt, '"'); if ($nq %2 == 0) { if ($nq > 0) { $elt = trim($elt); //Supprime les espaces encadrant les " qui limitent les éléments de la chaîne $elt = substr_replace($elt, '', strpos($elt, '"'), 1); $elt = substr_replace($elt, '', strrpos($elt, '"'), 1); $elt = str_replace('""', '"', $elt); } if ($trim) $out[] = trim($elt); else $out[] = $elt; $elt = ''; } } if ($elt == '') return $out; else return false; //La chaine contient un \n, à combiner avec la chaine suivante }
Séparation des champs d'une chaîne CSV vers un tableau à 2 dimensions
En javascript
La fonction javascript suivante retourne un tableau contenant les différents champs d'une chaîne CSV d'un ensemble de fiches, avec ou sans r.
String.prototype.parseCSV = function(sep , trim) { sep = sep || ","; var ch = '', out = [] , ax , ay , i; ay = this.replace(/[\r\n]*$/ , '').replace(/\r/g , '').split("\n"); for (i = 0; i < ay.length ; i++) { if (ch == '') ch = ay[i]; else ch += "\n" + ay[i]; ax = ch.splitCSV(sep, trim); if (ax !== false) { out.push(ax); ch = ''; } } if (ch == '') return out; else return false; //La chaîne est mal formée }
En php
La même fonction en php
function parseCSV($string , $sep="," , $trim = false) { $string = preg_replace('/[\r\n]*$/' , '' , $string); $ay = explode("\n" , str_replace("\r" , '' , $string)); //$ay = preg_split('/\r?\n/' , $string); $ch = ''; $out = array(); foreach($ay as $ligne) { if ($ch == '') $ch = $ligne; else $ch .= "\n$ligne"; $ax = splitCSV($ch , $sep, $trim); if ($ax !== false) { $out[] = $ax; $ch = ''; } } if ($ch == '') return $out; else return false; //La chaîne est mal formée }
Création d'une ligne CSV à partir d'un tableau à 1 dimension
En javascript
Array.prototype.joinCSV = function(sep) { var i, s , sep = sep || ',' ,val = this.slice(0); //Pour créer une copie de this car modifié dans la fonction for( i = 0 ; i < val.length ; i++) { if (typeof(val[i]) != 'string') val[i] = val[i].toString(); s = val[i].replace(/"/g , '""'); if (val[i] !== s || s.indexOf(sep) >= 0 || s.indexOf('\n') >= 0) val[i] = '"' + s + '"'; } return val.join(sep); }
En php
function joinCSV($a , $sep = ',') { $count = 0; foreach($a as $key => $val) { $val = str_replace('"' , '""' , $val , $count); if ($count > 0 || strpos($val , $sep) !== false || strpos($val , "\n") !== false) $a[$key] = '"' . $val . '"'; } return implode($sep , $a); }
Création d'une chaîne CSV à partir d'un tableau à 2 dimensions
En javascript
Array.prototype.makeCSV = function(sep) { var i, sep = sep || ',' , val = []; for (var i = 0 ; i < this.length ; i++) { val.push(this[i].joinCSV(sep)); } return val.join('\n'); }
En php
function makeCSV($a2 , $sep = ',') { $a = array(); foreach($a2 as $row) { $a[] = joinCSV($row , $sep); } return implode("\n" , $a); }