Leer y escribir CSV en Java con Apache Commons CSV

Este es el segundo artículo de una breve serie dedicada a las bibliotecas para leer y escribir archivos CSV en Java, y una continuación directa del artículo anterior:...

Introducción

This is the second article in a short series dedicated to Bibliotecas para leer y escribir CSV en Java, and a direct continuation from the previous article - Leer y escribir CSV en Core Java.

CSV de Apache Commons

La biblioteca Apache Commons CSV es la versión de Apache Software Foundation de un analizador Java CSV. Según el resumen del proyecto, intenta "proporcionar una interfaz sencilla para leer y escribir archivos CSV de varios tipos ".

Como todas las bibliotecas asociadas con Apache, opera con una licencia apache, lo que significa que puede usarse, distribuirse y modificarse libremente.

Apache Commons permite a los desarrolladores definir sus propios formatos, pero ofrece un conjunto predefinido de formatos con su [Clase CSVFormat](http://commons.apache.org/proper/commons-csv/apidocs/org/apache/commons/csv/ formato CSV.html).

Estos formatos predefinidos son:

  • RFC4180: formato separado por comas definido por RFC 4180.
  • DEFAULT - Similar al formato RFC4180, pero permite líneas vacías entre filas de datos. Este formato se usa, si no se especifica lo contrario, cuando define un analizador con la biblioteca Apache Commons CSV.
  • EXCEL - Similar a RFC 4180, pero permite que falten nombres de columnas e ignora las líneas vacías.
  • TDF - Formato predefinido para archivos CSV que están delimitados con tabulaciones (\t) en lugar de comas.
  • MYSQL - El formato soportado por las operaciones SELECT INTO OUTFILE y LOAD DATA INFILE de MySql.
  • ORACLE: formato CSV utilizado por el cargador Oracle SQL.
  • INFORMIX_UNLOAD e INFORMIX_UNLOAD_CSV: formatos especializados definidos para su uso con la base de datos integrada IBM Informix®.
  • MONGODB_CSV y MONGODB_TSV - Funciona con la base de datos poplar NoSQL MongoDB, para valores separados por comas y tabulaciones respectivamente.
  • POSTGRESQL_CSV y POSTGRESQL_TEXT - Formato soportado por bases de datos PostgreSQL.

Si necesita una solución muy simple, es posible que Apache Commons CSV no sea adecuado. La implementación está diseñada para ofrecer la máxima flexibilidad, lo que hace que el código fuente equivalga a unas 30.000 líneas y resulte bastante complejo de entender en algunos casos.

Sin embargo, si necesita cubrir una amplia variedad de formatos, Apache Commons es una biblioteca confiable, bien mantenida y actualizada regularmente, con una extensa documentación de Java Docs y desarrolladores para ayudar a los principiantes.

Está incluido en el repositorio de Maven Central y no tiene dependencias externas.

Leer archivos CSV con Apache Commons CSV

La biblioteca de Apache Commons ofrece varios métodos para acceder a campos individuales en un archivo CSV. Si está trabajando con aplicaciones como Excel, es probable que su CSV con formato de Excel tenga un encabezado.

Sin embargo, si está utilizando CSV como un conjunto básico de texto separado por comas, para transferir datos entre sistemas o para alimentar otra aplicación de procesamiento, el archivo puede contener datos a partir de la primera fila, sin encabezado. La biblioteca Apache Commons CSV tiene en cuenta estos dos escenarios.

Si su archivo CSV no contiene un encabezado, o si no está seguro de si lo contiene, puede usar el índice para acceder a un registro. Dado que CSVRecord implementa la Java Iterable Interface, el índice se basa en 0, aunque los índices CSV, cuando se abren con Excel y la mayoría de las otras aplicaciones, comienzan con 1:

1
2
3
4
5
6
CSVParser csvParser = CSVFormat.DEFAULT.parse(new InputStreamReader(csvFile.getInputStream()));
for (CSVRecord record : csvParser) {
    String field_1 = record.get(0);
    String field_2 = record.get(1);
    ...
}

Si está seguro de que el archivo CSV que necesita analizar tiene un encabezado y conoce el formato del encabezado antes de procesarlo, puede usar la cadena de la columna del encabezado para obtener registros.

Consideremos un archivo CSV de muestra con datos de árbol, y llamémoslo 'archivo CSV de datos de árbol\ ’ para futuras referencias en este artículo:


[Índice]{style=“font-weight:bold”} Circunferencia (pulgadas) Altura (pies) Volumen (pies) 1 8,3 70 10,3


Para referirnos a cada fila de datos podríamos usar la indexación como en el ejemplo anterior, o el encabezado de columna:

1
2
3
4
5
6
7
8
InputStreamReader input = new InputStreamReader(csvFile.getInputStream());
CSVParser csvParser = CSVFormat.EXCEL.withFirstRecordAsHeader().parse(input);
for (CSVRecord record : csvParser) {
    String field_1 = record.get("Index");
    String field_2 = record.get("Girth (in)");
    String field_3 = record.get("Height (ft)");
    String field_4 = record.get("Volume (ft)");
}

Si desea leer un archivo que no contiene una fila de encabezado, desea definir su propio encabezado o encuentra confusa la indexación, Apache Commons también permite la definición de un encabezado para el análisis.

En lugar de utilizar el método .withFirstRecordAsHeader() al definir el formato del archivo CSV, puede definir un encabezado manualmente. Por ejemplo, si desea evitar hacer referencia a las unidades de medida en el encabezado de nuestro archivo de datos de árbol, puede redefinir el encabezado para usar sus propios valores de cadena:

1
2
3
4
CSVParser csvParser = CSVFormat.REF4180.withHeader("Index", "Girth", "Height", "Volume");
for (CSVRecord record : csvParser) {
    String field_2 = record.get("Girth");
}

Si su archivo CSV contiene un encabezado, pero desea definir su propio encabezado y omitir la lectura del encabezado en el archivo, use .readNext() para omitir la primera fila:

1
2
CSVRecord header = csvParser.readNext();
// read the other rows in a loop as usual

También puede usar una enumeración para definir un encabezado si necesita usar su definición en varias clases como en este ejemplo:

1
2
3
4
5
6
public enum treeHeader {
    Index, Girth, Height, Volume
}
...
CSVParser csvParser = CSVFormat.DEFAULT.withHeader(treeHeader.class).parse(input);
// read rows

La biblioteca Apache Commons CSV tiene algunos métodos adicionales para facilitar el análisis, incluidos:

  • .getRecordNumber() - devuelve el número asignado al registro en el archivo CSV.
  • .isConsistent(): se puede usar para el manejo de errores, devuelve True o False en función de si el tamaño del registro actual coincide con el tamaño de la fila del encabezado.
  • .size() - puede usarse para determinar el número de valores en el registro.
  • .toString() - devuelve el registro como una cadena. Útil cuando necesita almacenar la fila completa como una cadena para su posterior procesamiento, hash o comparación.

Escribir CSV con Apache Commons CSV

La biblioteca Apache Commons CSV se centra principalmente en leer datos de archivos CSV. Cuando se trata de escribir, los métodos recomendados en la guía del usuario son bastante familiares para nuestra implementación principal de Java.

Sin embargo, hay algunas funciones adicionales útiles, como la capacidad de definir un encabezado al imprimir e imprimir directamente desde un objeto ResultSet de JDBC.

La clase CSVPrinter implementa las interfaces Flushable y Closeable, haciendo que su comportamiento sea similar a una extensión de un Writer o StringWriter habitual de Java.

Por ejemplo, para generar nuestro árbol de datos CSV:

1
2
3
CSVPrinter csvPrinter = new CSVPrinter(stringWriter, CSVFormat.DEFAULT.withHeader("Index", "Girth", "Height", "Volume"));
csvPrinter.printRecord("1", "8.3", "70", "10.3");
csvPrinter.flush();

El método .withHeader() acepta los valores de cadena del encabezado como parámetros.

Si desea generar un CSV sin encabezado, simplemente puede usar new CSVPrinter(stringWriter, CSVFormat.DEFAULT);.

Si desea utilizar los encabezados de columna de un ResultSet de JDBC existente para imprimir, Apache Commons CSV acepta un ResultSet como parámetro para su método .withHeader():

1
2
CSVPrinter csvPrinter = CSVFormat.RFC4180.withHeader(treeDataResultSet).print(out);
csvPrinter.printRecords(treeDataResultSet);

Si el CSVFormat que usa permite líneas vacías, puede usar csvPrinter.println() para imprimir una línea en blanco entre las filas de datos.

Además de un ResultSet, el método .printRecords() también puede trabajar con un Arreglo Iterable, o una Colección de Cadenas pasadas al método usando [varArgs](https://docs. oracle.com/javase/8/docs/technotes/guides/language/varargs.html).

Conclusión

Apache Commons CSV intenta proporcionar una interfaz simple para leer y escribir archivos CSV de varios tipos.

La implementación está diseñada para ofrecer la máxima flexibilidad, lo que hace que el código fuente sea bastante complejo de entender en algunos casos.

Sin embargo, si necesita cubrir una amplia variedad de formatos, Apache Commons es una biblioteca confiable, bien mantenida y actualizada regularmente, con una extensa documentación de Java Docs y desarrolladores para ayudar a los principiantes.

Licensed under CC BY-NC-SA 4.0