Toujours d’actualité, notre bon vieux fichier « CSV » (Comma separated values) est plus que jamais en vigueur pour stocker et partager une matrice* en format texte. Héritage du siècle dernier, c’était même la norme avec les premiers langages de programmation, notamment la tabulation, sans doute dérivé de la dactylo. Simple mais inefficace, j’avoue que ça dépanne toujours son homme !
Essentiellement à des fins d’exportation, le fichier texte CSV plutôt temporaire a conquis le mode de l’open source pour devenir, avec son petit frère Json plus sophistiqué (plus imbriqué), la norme d’aujourd’hui...du Web2! Il supporte toutefois très mal l’encodage « Unicode », malgré son support 8 bits (Business as usual!). Certains fils de presse vont jusqu’à importer un RSS pour le re-pondre en Json! Ajax oblige! Alors on peut bien parler de B2B et Wikipédia d’« échanges de données ponctuelles », les CMS, les jQuery, Excel, fichiers d’installation, de configuration. d’initialisation, vCard, iCalendar et des centaines de données du type CSV ponctuent aujourd’hui le « web commun » en temps réel. Un peu comme le gaz naturel, une aubaine du 21e siècle!
Enfin, en autant que ça ne réchauffe pas la planète, plus on est de fous et plus c’est drôle non ;- ) D’autant que du plaisir, on n’en manque pas, le CSV a aussi ses vertus!
Intuitif, le CSV s’impose de lui-même et persiste toujours malgré l’excellence du XML. Quoi de plus naturelle que de séparer des valeurs par des virgules! Imbriquer des séparateurs ne date pas d’hier parce qu’il suffit d’une seule commande en général pour la décomposer en matrice. Pensez aux requêtes HTTP (Query String) : champ1=valeur&champ=valeur&champ=valeur
. Le web communique de cette façon et la plupart des langages script n’y échappent pas et doivent s’y soumettre ;- ). Que ce soit l’ActionScript ou plus récemment l’Ajax! D’ailleurs, la première version des Trucsweb stockait chaque tutoriel dans un fichier texte indépendant avant de passer au XML. Fait non négligeable, le PHP a dû attendre la version 5 pour offrir un véritable support XML. Ça explique aussi beaucoup de choses.
Spécifications
Le fichier CSV est donc la représentation d’une matrice dans un fichier de type « texte/csv* » basé sur le principe de séparateur pour stocker des données, délimité ou non par des guillemets! Bien qu’il n’y est pas réellement de norme, on considère en général que :
L’objet FSO ne supporte pas l’encodage UTF-8
Le « file système object » du ASP (FSO) ne supporte absolument pas le format UTF-8 malgré les nombreuses spécifications affirmant le contraire. Notez qu’il est toutefois possible de gérer à merveille le UTF-8 et toute la grande famille « Unicode » avec l’objet « Microsoft.XMLDOM » (XML) ou encore avec l’objet « ADODB.Stream ».
- L’extension du fichier doit absolument être .csv;
- L’encodage doit être en format ASCII. L’UTF-8 est officiellement accepté, comme n’importe quel fichier texte mais à toute fin pratique jamais supportée. Quant au caractère BOM*, c’est le plantage assuré ! ;
- Chaque ligne du texte correspond à une ligne du tableau;
- La première ligne peut être utilisée comme entête des colonnes (Obligatoire selon certain auteur);
- Les virgules correspondent aux séparations entre les colonnes;
- Le guillemet double peut être utilisé pour délimiter les phrases.
Les données dites « tabulaires » peuvent être séparées par des virgules, des points-virgules, des tabulations, la position, à peu près n’importe quoi! Les textes délimités par des guillemets permettent d’inclure par exemple des virgules, des espaces et même d’autres guillemets doublés pour les distinguer du délimiteur.
Téléchargez le fichier CSV de l’exemple Par exemple :
"Pays","ISO 2","ISO 3"
France,FR,FRA
Canada,CA,CAN
Québec,QC,QUE
Solution #1 : Ouvrir un fichier CSV avec la méthode conventionnelle FSO
Quoi de plus banale que d’ouvrir un fichier et le lire ligne par ligne avec la méthode ReadLine
de l’objet FSO? Il suffit ensuite de scinder en matrice sur le séparateur (split
) chaque ligne du fichier. Le problème avec cette technique, outre le support UTF-8, est l’impossibilité de revenir en arrière. C’est-à-dire qu’il faut rouvrir le fichier pour refaire la boucle. En général ça fait le travail, surtout s’il s’agit d’une importation qui implique en principe la capture de l’ensemble des données. Il suffit d’ajouter quelques tests de conditions et manipulation de chaine de caractères pour traiter l’information et le tour est joué.
Même si la solution plus bas ADODB.Stream (UTF-8) supporte l’encodage « Unicode », l’objet FSO (ASCII) doit être privilégié pour une meilleurs compatibilité.
Version FSO ASP
<table class="table table-striped table-bordered table-hover table-condensed"> <% dim nCompteur, fso, sNomFichier, oFichier, aLigne sNomFichier = "country-code-fr.csv" nCompteur = 0 set fso = createobject("scripting.filesystemobject") set oFichier = fso.opentextfile(server.mappath(sNomFichier)) Do Until oFichier.AtEndOfStream nCompteur = nCompteur + 1 aLigne = split(oFichier.ReadLine,",") Response.Write "<tr>" if nCompteur > 1 Then for i = 0 to ubound(aLigne) Response.Write "<td>"&aLigne(i)&"</td>" next else for i = 0 to ubound(aLigne) Response.Write "<th>"&aLigne(i)&"</th>" next end if Response.Write "</tr>" & chr(13) Loop objFile.Close %> <caption>Nombre total de pays : <%=nCompteur-1%></caption> </table>
Solution #2 : L’objet ADODB.Stream
Bien que l’objet ADODB. Stream offre enfin un véritable support « Unicode » par défaut UTF-16, il reste incompatible pour la plupart des systèmes. Personnellement j’utilise le format CSV exclusivement à des fins d’importation et d’exportation généralement pour le format Excel. J’utilise donc pratiquement toujours la version FSO, en d’autre mots une conversion manuelle avec mon éditeur de texte.
Version ADODB.Stream ASP
<table class="table table-striped table-bordered table-hover table-condensed"> <% dim sNomFichier, aLigne, oStream, nCompteur sNomFichier = "country-code-fr-utf-8.csv" Set oStream = CreateObject("ADODB.Stream") oStream.Charset = "utf-8" oStream.Type = 2 oStream.Open oStream.LoadFromFile server.mappath(sNomFichier) oStream.LineSeparator = 10 nCompteur = 0 Do Until oStream.EOS nCompteur = nCompteur + 1 aLigne = split(oStream.ReadText(-2),",") Response.Write "<tr>" if nCompteur > 1 Then for i = 0 to ubound(aLigne) Response.Write "<td>"&aLigne(i)&"</td>" next else for i = 0 to ubound(aLigne) Response.Write "<th>"&aLigne(i)&"</th>" next end if Response.Write "</tr>" & chr(13) Loop oStream.Close %> <caption>Nombre total de pays : <%=nCompteur-1%></caption> </table>
Solution #3 : Convertir en base de données!
Mais qu’est-ce qu’arrive s’il faut remonter à la première ligne? Et a-t-on toujours besoin de lire chaque ligne du fichier pour trouver un seul enregistrement? Etc. L’objet FSO n’est pas fait pour ce type de tâche. Alors à défaut de passer au XML, que diriez-vous si une solution encore plus simple vous permettait de convertir non seulement votre fichier en base de données mais aussi de l’interroger à l’aide du langage SQL et des méthodes ADO! Eh oui, en une seule ligne, une autre chaine, cette fois de connexion !
Provider=Microsoft.Jet.OLEDB.4.0; Data Source=[Chemin/Path];Extended Properties=""text;HDR=YES;FMT=Delimited;
Version ADO ASP
<% Const adOpenStatic = 3 Const adLockOptimistic = 3 Const adCmdText = &H0001 dim oConn : Set oConn = CreateObject("ADODB.Connection") dim oRS : Set oRS = CreateObject("ADODB.Recordset") dim sChemin : sChemin = Server.MapPath("\")&"\documents" dim sFichier : sFichier = "country-code-fr-ASCII.csv" dim sSql : sSql = "SELECT * FROM [" & strPathtoTextFile2 &"]" oConn.Open "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=" & sChemin & ";Extended Properties=""text;HDR=YES;FMT=Delimited;""" oRS.Open sSql, oConn, 1, 3, &H0001 ’objRecordset.Charset = "UTF-8" ’Response.CharSet = "UTF-8" if oRS.EOF then Response.Write "Aucune donnée" else Do Until oRS.EOF response.write " " & oRS.Fields.Item("Pays") response.write " " & oRS.Fields.Item("ISO2") response.write " " & oRS.Fields.Item("ISO3") response.write " " & oRS.Fields.Item("ISOON") response.write "
" oRS.MoveNext Loop end if oRS.close set oRS = nothing oConn.close set oConn = nothing %>
Références
Common Format and MIME Type for Comma-Separated Values (CSV) Files CSV File Format Specification