CSV (Comma-Separated Values) é o formato tabular mais simples que existe: as linhas do arquivo correspondem às linhas da tabela e os valores dentro de cada linha são separados por vírgula ou outro caractere. Nele chegam as exportações dos CRMs e ERPs, os downloads do Excel, os relatórios das plataformas de publicidade e de analítica. O formato parece trivial, e justamente por isso é onde mais se cometem erros. Este artigo faz parte do nosso panorama do parsing de documentos e é dedicado a como ler CSV corretamente.
Por que o «split por vírgulas» é um erro
A tentação de fatiar o CSV à mão — line.split(",") — todo mundo sente, e quase sempre termina em bugs. A razão é que o CSV tem escape: um valor com vírgula dentro é envolvido em aspas, e as aspas dentro de um valor são duplicadas.
sku,name,price
101,"Moedor de café, manual",3490
102,"Bule ""Retrô""",2190Aqui "Moedor de café, manual" é um único valor, não dois, e Bule "Retrô" contém aspas. Qualquer split manual vai quebrá-lo. Por isso usa-se sempre um leitor de CSV pronto: ele conhece as aspas, o escape e as quebras de linha dentro das células.
Separadores, codificações e BOM
Apesar do «comma» no nome, o separador muitas vezes acaba sendo o ponto e vírgula (;): é assim que o Excel salva os arquivos nas configurações regionais onde a vírgula é o separador decimal — a brasileira entre elas. Também aparecem a tabulação (TSV) e a barra vertical. Um bom parser sabe detectar o separador automaticamente ou o aceita como parâmetro.
O segundo problema constante é a codificação. Os arquivos dos sistemas de gestão antigos chegam com frequência em windows-1252 (latin-1), e não em UTF-8. Além disso, os arquivos do Excel muitas vezes começam com um BOM (uma marca invisível no início) por culpa do qual o nome da primeira coluna é lido como sku em vez de sku. Cura-se indicando a codificação correta na leitura (em Python, encoding="utf-8-sig", que elimina o BOM sozinha).
Python
A biblioteca padrão inclui o módulo csv, suficiente na maioria dos casos. O mais prático é o DictReader, que entrega cada linha como um dicionário conforme os cabeçalhos.
import csv
with open("prices.csv", encoding="utf-8-sig", newline="") as f:
reader = csv.DictReader(f, delimiter=";")
for row in reader:
print(row["sku"], row["name"], row["price"])Quando o CSV é grande ou é preciso analisá-lo em tempo real — filtrar, agrupar, calcular —, recorre-se ao pandas. Uma única linha lê o arquivo para uma tabela (DataFrame).
import pandas as pd
df = pd.read_csv("prices.csv", sep=";", encoding="utf-8-sig")
expensive = df[df["price"] > 3000]
print(expensive[["sku", "name"]])O pandas também é prático para converter: esse mesmo DataFrame é salvo com um único comando de volta em CSV, Excel ou JSON.
JavaScript / Node.js
No navegador e no Node, o parser mais popular é o Papa Parse: detecta o separador automaticamente, entende os cabeçalhos e sabe trabalhar com fluxos.
const Papa = require("papaparse");
const fs = require("fs");
const file = fs.readFileSync("prices.csv", "utf-8");
const result = Papa.parse(file, { header: true, skipEmptyLines: true });
for (const row of result.data) {
console.log(row.sku, row.name, row.price);
}Para os pipelines de servidor com arquivos grandes, escolhe-se com mais frequência o csv-parse — o parser em fluxo do ecossistema Node CSV.
PHP
A função nativa fgetcsv já incorpora o tratamento das aspas, então basta para as tarefas simples.
<?php
$f = fopen("prices.csv", "r");
$headers = fgetcsv($f, 0, ";");
while (($row = fgetcsv($f, 0, ";")) !== false) {
$record = array_combine($headers, $row);
echo $record["sku"] . " — " . $record["name"] . "\n";
}
fclose($f);Para um trabalho mais confortável — com filtragem, seleção de colunas e conversão de codificações — usa-se a biblioteca league/csv.
Go
A biblioteca padrão de Go traz o pacote encoding/csv, que cobre a maioria dos casos, separador fora do padrão incluído.
package main
import (
"encoding/csv"
"fmt"
"os"
)
func main() {
f, _ := os.Open("prices.csv")
defer f.Close()
r := csv.NewReader(f)
r.Comma = ';'
rows, _ := r.ReadAll()
for _, row := range rows[1:] { // pulamos a linha de cabeçalho
fmt.Println(row[0], row[1], row[2])
}
}Quando o CSV deixa de dar conta
O CSV funciona enquanto os dados são planos. Assim que aparecem aninhamento, várias tabelas em um mesmo arquivo, formatação, fórmulas ou células mescladas, isso já não é tarefa para CSV, e sim para o parsing de Excel. E o contrário também vale: se o original em Excel é complexo demais para ser lido diretamente, muitas vezes exporta-se primeiro para CSV e processa-se de maneira uniforme. E se o CSV é, no fundo, um despejo de eventos ou de linhas de um registro, dê uma olhada nas abordagens dos artigos sobre o parsing de TXT e o parsing de logs.
Se os seus downloads chegam com codificações «flutuantes», separadores que mudam de uma entrega para outra ou aspas quebradas, nós os unificamos e configuramos um parsing estável com a carga do resultado no sistema de que você precisa.