4 - Lectura de CSV en C# y JavaScript, y Escritura de CSV

Lectura de CSV en C#

Para C#, la biblioteca CsvHelper es una opción muy popular y robusta para leer y escribir archivos CSV. Es altamente configurable y maneja bien los casos complejos.

Primero, instala el paquete NuGet CsvHelper:

dotnet add package CsvHelper

Ejemplo de archivo datos.csv:

Id,Producto,Precio
1,Manzana,1.20
2,Pera,0.85
3,"Naranja, dulce",1.50

Código C# para leer datos.csv con CsvHelper:

using CsvHelper;
using CsvHelper.Configuration;
using System.Globalization;

public class Producto
{
    public int Id { get; set; }
    public string Producto { get; set; }
    public decimal Precio { get; set; }
}

public class CsvReaderExample
{
    public static void Main(string[] args)
    {
        var config = new CsvConfiguration(CultureInfo.InvariantCulture)
        {
            HasHeaderRecord = true,
        };

        using (var reader = new StreamReader("datos.csv"))
        using (var csv = new CsvReader(reader, config))
        {
            var records = csv.GetRecords<Producto>().ToList();
            foreach (var p in records)
            {
                Console.WriteLine($"Id: {p.Id}, Producto: {p.Producto}, Precio: {p.Precio}");
            }
        }
    }
}

Explicación:

  • Se define una clase Producto que mapea las columnas del CSV.
  • CsvConfiguration permite configurar el delimitador, si hay encabezados, etc. CultureInfo.InvariantCulture es importante para asegurar que los números se parseen correctamente independientemente de la configuración regional.
  • csv.GetRecords<Producto>() lee automáticamente el CSV y lo mapea a una lista de objetos Producto.

Lectura de CSV en JavaScript

En JavaScript, la lectura de CSV puede variar si se hace en el navegador (usando FileReader para archivos locales o fetch para URLs) o en Node.js (usando módulos de sistema de archivos). Para ambos entornos, bibliotecas como PapaParse simplifican mucho la tarea.

Usando PapaParse (navegador y Node.js)

PapaParse es una potente biblioteca para parsear CSV en JavaScript, manejando automáticamente delimitadores, comillas, y conversiones de tipos.

Puedes incluirla vía CDN en HTML:

<script src="https://unpkg.com/papaparse@5.4.1/papaparse.min.js"></script>

Ejemplo de lectura de un archivo local (HTML + JS):

<input type="file" id="csvFile" accept=".csv">
<pre id="output"></pre>

<script>
  document.getElementById('csvFile').addEventListener('change', function(event) {
    const file = event.target.files[0];
    Papa.parse(file, {
      header: true,
      complete: function(results) {
        document.getElementById('output').textContent = JSON.stringify(results.data, null, 2);
        console.log("Parsed CSV:", results.data);
      },
      error: function(err) {
        console.error("Error parsing CSV:", err);
      }
    });
  });
</script>

Explicación:

  • El usuario selecciona un archivo CSV a través de un input de tipo file.
  • Papa.parse() toma el archivo y un objeto de configuración. header: true indica que la primera fila son encabezados.
  • El callback complete se ejecuta cuando el parseo termina, y results.data contiene los datos como un array de objetos.

Usando FileReader (navegador, para archivos locales)

Para archivos CSV muy simples y sin dependencias externas, puedes usar la API FileReader del navegador.

<input type="file" id="csvFileSimple" accept=".csv">
<pre id="outputSimple"></pre>

<script>
  document.getElementById('csvFileSimple').addEventListener('change', function(event) {
    const file = event.target.files[0];
    const reader = new FileReader();

    reader.onload = function(e) {
      const text = e.target.result;
      const lines = text.split('\n');
      const headers = lines[0].split(',');
      const data = [];

      for (let i = 1; i < lines.length; i++) {
        if (lines[i].trim() === '') continue; // Ignorar líneas vacías
        const values = lines[i].split(',');
        const row = {};
        for (let j = 0; j < headers.length; j++) {
          row[headers[j]] = values[j];
        }
        data.push(row);
      }
      document.getElementById('outputSimple').textContent = JSON.stringify(data, null, 2);
      console.log("Parsed CSV (simple):
", data);
    };

    reader.readAsText(file);
  });
</script>

Explicación:

  • FileReader lee el contenido del archivo como texto.
  • El contenido se divide por saltos de línea y luego cada línea por comas.
  • Este método es más propenso a errores si el CSV no es perfectamente simple (ej. comas dentro de campos).

Escritura de CSV

La escritura de archivos CSV es el proceso inverso a la lectura: tomar datos estructurados (desde un programa, una base de datos, etc.) y convertirlos en el formato de texto plano CSV.

Crear un CSV desde un programa

La mayoría de los lenguajes de programación ofrecen módulos o bibliotecas para escribir datos en formato CSV.

Ejemplo en Python (usando el módulo csv):

import csv

datos = [
    ['Nombre', 'Edad', 'Ciudad'],
    ['Pedro', 28, 'Sevilla'],
    ['Maria', 32, 'Malaga'],
    ['Luis', 45, '"Granada, España"' ] # Campo con coma interna
]

with open('salida.csv', mode='w', newline='', encoding='utf-8') as file:
    writer = csv.writer(file)
    writer.writerows(datos)

print("Archivo salida.csv creado exitosamente.")

Explicación:

  • newline='' es importante para evitar que se inserten líneas en blanco adicionales en Windows.
  • csv.writer crea un objeto escritor.
  • writerows() escribe todas las filas de una lista de listas. El módulo csv se encarga automáticamente de las comillas si un campo contiene el delimitador.

Ejemplo en Java (usando OpenCSV):

import com.opencsv.CSVWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class EscribirCsvOpenCsv {
    public static void main(String[] args) {
        String fileName = "salida.csv";

        List<String[]> datos = new ArrayList<>();
        datos.add(new String[]{"Nombre", "Edad", "Ciudad"});
        datos.add(new String[]{"Pedro", "28", "Sevilla"});
        datos.add(new String[]{"Maria", "32", "Malaga"});
        datos.add(new String[]{"Luis", "45", "Granada, España"});

        try (CSVWriter writer = new CSVWriter(new FileWriter(fileName))) {
            writer.writeAll(datos);
            System.out.println("Archivo " + fileName + " creado exitosamente.");
        } catch (IOException e) {
            System.err.println("Error al escribir el archivo CSV: " + e.getMessage());
        }
    }
}

Explicación:

  • CSVWriter se encarga de formatear los datos correctamente, incluyendo el manejo de comillas.
  • writeAll() escribe una lista de arrays de cadenas al archivo.

Exportar datos a CSV desde una base de datos

La mayoría de los sistemas de gestión de bases de datos (DBMS) ofrecen funcionalidades para exportar los resultados de una consulta directamente a un archivo CSV.

  • MySQL: Puedes usar la sentencia SELECT ... INTO OUTFILE.
    SELECT id, nombre, email
    FROM usuarios
    INTO OUTFILE '/tmp/usuarios.csv'
    FIELDS TERMINATED BY ','
    ENCLOSED BY '"'
    LINES TERMINATED BY '\n';
  • PostgreSQL: Utiliza el comando COPY.
    COPY (SELECT id, nombre, email FROM usuarios) TO '/tmp/usuarios.csv' WITH CSV HEADER;
  • SQLite: Desde la línea de comandos, puedes configurar el modo CSV y luego ejecutar una consulta.
    sqlite3 database.db
    .mode csv
    .headers on
    .output usuarios.csv
    SELECT id, nombre, email FROM usuarios;
    .quit

Generar reportes automatizados

La capacidad de escribir CSV programáticamente es fundamental para la generación de reportes automatizados. Por ejemplo, un script Python puede:

  1. Conectarse a una base de datos.
  2. Ejecutar una consulta compleja para obtener datos.
  3. Procesar y transformar esos datos.
  4. Escribir los resultados en un archivo CSV.
  5. Enviar el archivo CSV por correo electrónico o subirlo a un servidor FTP.

Esto es muy común en tareas de ETL (Extract, Transform, Load) y en la creación de dashboards o informes periódicos para negocios.