CSV est l'un de ces formats que personne n'aime mais que tout le monde utilise. Il existe depuis les années 1970, c'est encore le format d'exportation par défaut de chaque application de feuille de calcul sur la planète, et il se trouve probablement quelque part dans votre pipeline de données en ce moment. Le format semble trivialement simple — juste des valeurs séparées par des virgules — mais l'analyser correctement est étonnamment facile à rater. Passons en revue comment il fonctionne réellement, où ça se complique, et comment le gérer en Python et JavaScript sans vous tirer une balle dans le pied.

Ce qu'est réellement CSV

CSV signifie Comma-Separated Values (valeurs séparées par des virgules). Un fichier CSV est du texte brut — pas d'encodage binaire, pas de métadonnées, pas de structure au-delà des lignes et des colonnes. Chaque ligne est un enregistrement, chaque valeur dans une ligne est séparée par un délimiteur (généralement une virgule), et la première ligne est conventionnellement une ligne d'en-tête avec des noms de colonnes. Voici à quoi ressemble un vrai CSV :

text
order_id,customer,product,quantity,unit_price,shipped
1001,Alice Nguyen,USB-C Hub,2,34.99,true
1002,Bob Martinez,Mechanical Keyboard,1,129.00,false
1003,Alice Nguyen,HDMI Cable,3,12.50,true
1004,Carol Smith,Webcam 1080p,1,79.95,false

C'est tout — six colonnes, quatre lignes de données et un en-tête. Pas de chevrons, pas d'accolades, pas de guillemets nécessaires (pour l'instant). Cette simplicité est exactement pourquoi CSV persiste : presque tout outil sur terre peut l'ouvrir, le lire et le produire. Excel, Google Sheets, la commande COPY de PostgreSQL, pandas, read.csv() de R — tout CSV d'emblée. La contrepartie est que le format a presque aucune structure : pas de types, pas d'imbrication, pas de schéma. Chaque valeur est une chaîne jusqu'à ce que vous en décidiez autrement.

RFC 4180 — La norme qui n'est pas vraiment appliquée

Il existe une spécification : RFC 4180, publiée en 2005. Elle définit des choses comme les fins de ligne CRLF, l'échappement des guillemets doubles, et comment gérer les virgules intégrées. Mais voilà — RFC 4180 est informatif, pas une norme. Il décrit ce qui était déjà une pratique courante, et non une législation. Personne n'est obligé de le suivre, et en pratique, presque personne ne le suit exactement.

Le résultat est le chaos des dialectes CSV. Vous avez des fichiers qui utilisent LF au lieu de CRLF, des fichiers où la première ligne peut ou non être un en-tête, des fichiers avec une nouvelle ligne finale et des fichiers sans, des fichiers avec un BOM UTF-8 ajouté par Excel. L' article Wikipedia sur CSV présente un bon résumé de tout ce qui varie en pratique. L'approche la plus sûre : ne jamais rien supposer sur un fichier CSV que vous n'avez pas produit vous-même, et toujours utiliser un analyseur approprié plutôt que de naïvement diviser sur les virgules.

Règles de citation : quand les virgules apparaissent dans les valeurs

C'est là que "juste diviser sur les virgules" s'effondre. Que se passe-t-il quand une valeur contient une virgule ? Ou une nouvelle ligne ? Ou un guillemet double ? RFC 4180 — et la plupart des analyseurs réels — gère cela en enveloppant le champ dans des guillemets doubles. Voici l'ensemble complet des règles :

  • Si un champ contient une virgule, une nouvelle ligne ou un guillemet double, enveloppez tout le champ dans des guillemets doubles
  • Si un champ contient un guillemet double, échappez-le en le doublant ("")
  • Les champs cités peuvent s'étendre sur plusieurs lignes — la nouvelle ligne fait partie de la valeur
  • Les espaces à l'intérieur des guillemets sont significatifs et doivent être préservés
text
order_id,customer,notes,unit_price
1005,David Lee,"Wants gift wrapping, express shipping",45.00
1006,Emma Brown,"Said: ""please handle with care""",89.99
1007,Frank Wu,"Address:
123 Main St
Apt 4B",15.50

Dans cet exemple : les notes de David contiennent une virgule, donc elles sont citées. La note d'Emma contient des guillemets doubles, donc ils sont doublés à l'intérieur des guillemets extérieurs. L'adresse de Frank s'étend sur plusieurs lignes — les sauts de ligne font partie de la valeur. Un naïf line.split(',') dans n'importe quel langage va complètement déformer ces trois exemples. C'est pourquoi vous avez besoin d'un vrai analyseur.

La règle d'or de l'analyse CSV : Ne jamais diviser sur les virgules manuellement. Utilisez toujours une bibliothèque d'analyse CSV dédiée. Elle gère les citations, les séquences d'échappement, les champs multilignes et l'encodage — rien de tout cela ne peut être fait correctement par un simple split.

Variantes de délimiteurs : tabulations, points-virgules, pipes

Malgré le nom, CSV n'a pas à utiliser des virgules. Plusieurs variantes courantes utilisent différents délimiteurs, et vous les rencontrerez toutes dans la nature :

  • TSV (Tab-Separated Values) — utilise \t comme délimiteur. Courant en bioinformatique (sortie BLAST, fichiers VCF), exports de base de données, et partout où les valeurs elles-mêmes contiennent fréquemment des virgules
  • Séparé par des points-virgules — le format par défaut dans Excel pour les paramètres régionaux où la virgule est le séparateur décimal (Allemagne, France, la plupart de l'UE). Si vous avez déjà ouvert un CSV d'un collègue européen et obtenu une seule colonne géante, c'est pourquoi
  • Séparé par des pipes — utilise |. Courant dans les anciens exports de données bancaires et d'assurance où les tabulations pourraient être supprimées par les systèmes mainframe
  • Largeur fixe — pas techniquement CSV, mais souvent regroupé dans la même catégorie. Les colonnes sont remplies à des largeurs fixes plutôt que délimitées

La plupart des analyseurs CSV vous permettent de spécifier le délimiteur explicitement. Lorsque vous écrivez un CSV que d'autres consommeront, documentez votre délimiteur. Lorsque vous lisez un que vous n'avez pas produit, vérifiez les premières lignes avant de supposer. Le Formateur CSV peut vous aider à inspecter et reformater des fichiers avec des délimiteurs non standard.

Analyse CSV en Python

La bibliothèque standard de Python inclut le module csv, et il est vraiment bon. Les deux classes que vous utiliserez le plus sont csv.reader pour un accès en ligne sous forme de liste et csv.DictReader pour un accès en ligne sous forme de dictionnaire (ce qui est presque toujours ce que vous voulez).

python
import csv

# csv.reader — each row is a list of strings
with open('orders.csv', 'r', encoding='utf-8', newline='') as f:
    reader = csv.reader(f)
    header = next(reader)          # consume the header row
    for row in reader:
        order_id, customer, product, quantity, price, shipped = row
        print(f"Order {order_id}: {quantity}x {product} for {customer}")

# csv.DictReader — each row is an OrderedDict keyed by the header
with open('orders.csv', 'r', encoding='utf-8', newline='') as f:
    reader = csv.DictReader(f)
    for row in reader:
        if row['shipped'] == 'false':
            print(f"Pending: {row['order_id']} — {row['customer']}")

Deux choses à toujours inclure : encoding='utf-8' (ou ce que le fichier utilise réellement), et newline=''. Ce deuxième est critique — le module csv fait sa propre gestion des nouvelles lignes et a besoin des octets bruts. Sans newline='', vous pouvez obtenir des lignes vides supplémentaires sous Windows.

L'écriture est tout aussi simple avec csv.writer :

python
import csv

orders = [
    {'order_id': 1008, 'customer': 'Grace Kim', 'product': 'Laptop Stand', 'quantity': 1, 'unit_price': 49.99, 'shipped': False},
    {'order_id': 1009, 'customer': 'Henry Park', 'product': 'USB-C Hub', 'quantity': 2, 'unit_price': 34.99, 'shipped': True},
]

with open('new_orders.csv', 'w', encoding='utf-8', newline='') as f:
    fieldnames = ['order_id', 'customer', 'product', 'quantity', 'unit_price', 'shipped']
    writer = csv.DictWriter(f, fieldnames=fieldnames)

    writer.writeheader()
    writer.writerows(orders)

# To use a different delimiter (e.g. tab-separated)
with open('new_orders.tsv', 'w', encoding='utf-8', newline='') as f:
    writer = csv.writer(f, delimiter='\t')
    writer.writerow(['order_id', 'customer', 'product'])
    writer.writerow([1008, 'Grace Kim', 'Laptop Stand'])

Le module csv gère automatiquement toutes les citations — si un champ contient une virgule ou une nouvelle ligne, il l'enveloppe dans des guillemets doubles sans que vous ayez à y penser. C'est tout l'intérêt d'utiliser une bibliothèque.

Analyse CSV en JavaScript / Node.js

JavaScript n'a pas d'analyseur CSV intégré. La tentation est de faire ceci :

js
// ❌ Don't do this — breaks immediately on quoted fields
const rows = csvText.split('\n').map(line => line.split(','));

Cela échoue dès qu'une valeur contient une virgule, une nouvelle ligne à l'intérieur des guillemets ou un guillemet double échappé. Pour tout ce qui est réel, utilisez une bibliothèque. PapaParse est le choix par défaut — il est rapide, gère tous les cas limites, fonctionne dans le navigateur et Node.js, et supporte le streaming pour les gros fichiers.

js
import Papa from 'papaparse';
import fs from 'fs';

// Parse a CSV string
const csvText = fs.readFileSync('orders.csv', 'utf8');

const result = Papa.parse(csvText, {
  header: true,          // first row becomes object keys
  skipEmptyLines: true,  // ignore blank lines at end of file
  dynamicTyping: true,   // converts "true"/"false" to booleans, numbers to numbers
});

console.log(result.data);
// [
//   { order_id: 1001, customer: 'Alice Nguyen', product: 'USB-C Hub', quantity: 2, unit_price: 34.99, shipped: true },
//   { order_id: 1002, customer: 'Bob Martinez', product: 'Mechanical Keyboard', quantity: 1, unit_price: 129, shipped: false },
//   ...
// ]

// Check for parse errors
if (result.errors.length > 0) {
  console.error('Parse errors:', result.errors);
}

// Generate CSV from an array of objects
const orders = [
  { order_id: 1008, customer: 'Grace Kim', product: 'Laptop Stand', quantity: 1, unit_price: 49.99 },
  { order_id: 1009, customer: 'Henry Park', product: 'USB-C Hub', quantity: 2, unit_price: 34.99 },
];

const csvOutput = Papa.unparse(orders);
fs.writeFileSync('export.csv', csvOutput, 'utf8');

L'option dynamicTyping est pratique mais vaut la peine d'être connue — elle convertit des choses comme "34.99" en nombre automatiquement. C'est généralement ce que vous voulez, mais ça peut vous surprendre si un champ comme order_id est un nombre dans le CSV mais que vous le vouliez comme chaîne. Désactivez-le si vous avez besoin d'une sortie strictement en chaîne.

Pour des conversions rapides entre CSV et d'autres formats, l'outil CSV vers JSON gère la plupart des cas courants dans le navigateur sans aucun code — utile pour les transformations de données ponctuelles. Il y a aussi CSV vers XML si vous avez besoin d'alimenter les données dans un système basé sur XML.

Pièges courants que vous rencontrerez certainement

Même avec un bon analyseur, CSV a quelques mines bien connues. Voici celles qui apparaissent le plus souvent :

  • Octets BOM d'Excel. Quand Excel exporte un CSV en "UTF-8", il ajoute souvent un BOM UTF-8 (EF BB BF en hexadécimal, ou \ufeff comme caractère). Cela fait que le premier nom de colonne ressemble à order_id au lieu de order_id. En Python, ouvrez le fichier avec encoding='utf-8-sig' au lieu de utf-8 pour le supprimer automatiquement. PapaParse le gère de manière transparente.
  • Fins de ligne CRLF vs LF. RFC 4180 spécifie CRLF (\r\n), mais les outils Unix produisent LF (\n) et les anciens fichiers Mac utilisent CR (\r) seul. C'est pourquoi le module csv de Python a besoin de newline='' — il gère les trois en interne. Si vous lisez des octets bruts et divisez manuellement, vous devez supprimer \r explicitement.
  • Problèmes d'encodage. CSV n'a aucun moyen de déclarer son propre encodage — contrairement au <meta charset> de HTML ou au <?xml encoding="..."?> de XML. Excel enregistre souvent les fichiers en Windows-1252 (a.k.a. CP1252) plutôt qu'UTF-8, ce qui déforme les caractères accentués. Si vous voyez des caractères comme é au lieu de é, vous avez un fichier UTF-8 décodé en Latin-1, ou vice versa. Établissez toujours l'encodage hors bande avec celui qui produit le fichier.
  • Nombres qui ressemblent à des dates. Excel convertit silencieusement des valeurs comme 1-2 ou 03/04 en dates lors de l'ouverture ou de la sauvegarde. Si vous exportez des codes de produits ou des numéros de version, préfixez-les d'une apostrophe dans Excel ('1-2) pour éviter cela — ou dites à celui qui produit le fichier de le faire.
  • Virgules finales. Certains exportateurs émettent une virgule finale à la fin de chaque ligne, ce qui crée une colonne vide fantôme. Un analyseur robuste l'ignore ; un simple split crée un élément de chaîne vide supplémentaire.

Si vous traitez un fichier qui semble bizarre, le Validateur CSV peut rapidement vous dire si le fichier est bien formé et signaler des problèmes d'encodage ou de structure avant que vous essayiez de le traiter.

CSV vs JSON vs Excel — Quand utiliser quoi

Ces trois formats se chevauchent beaucoup en pratique, mais chacun a une niche claire :

  • Utilisez CSV quand vous déplacez des données tabulaires plates entre des systèmes — exports de base de données, pipelines d'analyse, imports de feuilles de calcul, chargement de données en masse. Il est universellement pris en charge, minuscule en taille et trivialement diffable dans git. La contrainte : il est plat. Pas d'imbrication, pas de types, pas de relations.
  • Utilisez JSON quand les données sont hiérarchiques ou quand le schéma est important. Une commande avec plusieurs lignes, un fichier de configuration avec des objets imbriqués, une réponse API — ce sont naturellement du JSON. CSV vous forcerait à dénormaliser les données ou à inventer votre propre convention d'imbrication. La spécification JSON est claire et sans ambiguïté ; le format préserve les types (nombres, booléens, null, tableaux, objets).
  • Utilisez Excel (.xlsx) quand la sortie est pour des humains, pas des machines. Mise en forme, formules, plusieurs feuilles, graphiques — si un utilisateur professionnel est le consommateur final, Excel est souvent le bon choix. Ne l'utilisez jamais comme format d'échange entre systèmes. La spécification OOXML est énorme et le format est fragile entre les versions.

Il y a une heuristique pratique : si vous visualiseriez naturellement les données dans une feuille de calcul, CSV est probablement bien. Si vous les visualiseriez dans un arbre ou un éditeur de code, utilisez JSON. Si vous les envoyez à un acteur commercial qui filtrera et triera, utilisez Excel.

Conclusion

CSV est simple par conception et étonnamment délicat en pratique. Le format n'a pas de norme appliquée, existe en plusieurs variantes de délimiteurs, et repose sur des règles de citation qui brisent toute tentative d'analyse manuelle. La correction est toujours la même : utilisez un vrai analyseur (le module csv intégré de Python, ou PapaParse en JavaScript), spécifiez toujours l'encodage explicitement, et faites attention aux octets BOM d'Excel. Une fois que vous disposez d'un analyseur fiable en place, CSV est en fait un excellent format — rapide à produire, facile à inspecter dans n'importe quel éditeur de texte, et pris en charge partout. Pour le travail quotidien avec des fichiers CSV, les outils CSV vers JSON, Formateur CSV, et Validateur CSV gèrent les opérations courantes sans écrire une ligne de code.