lundi 20 février 2012

MoteurCsv le JPA du CSV

Voici un titre qui va faire gonfler mes chevilles :)
Je vais donc vous présenter une petite librairie Java sans prétention que j'ai réalisé afin de pourvoir lire et écrire des fichiers CSV facilement.

C'est quoi le CSV?

Bon pour la définition du format CSV, je vous invite à consulter l'article wikipedia.

Pourquoi cette librairie?

Cette librairie a été crée afin de pouvoir gérer le format GTFS. Ce format est utilisé afin de décrire un réseau de Transports en commun. Techniquement, c'est un zip contenant des fichiers CSV.
J'ai eu à utiliser ce format suite à l'ouverture des données de transports à Rennes où j'ai réalisé une application Android (Transports Rennes) permettant de consulter les horaires de bus.
A l'époque où j'ai créé cette librairie, je baignais dans du JPA la journée, et j'avoue que j'aime beaucoup l'idée de décrire du mapping directement dans la classe associé en utilisant des annotations.
C'est comme ça que MoteurCsv est né.

Alors comment ça s'utilise?

J'ai essayé de simplifier au maximun l'utilisation de la librairie.

Installation

Maven

Si vous êtes sous maven, l'intégration dans votre projet est très simple.
Il suffit d'ajouter dans votre pom.xml :
<dependencies>
    <dependency>
        <groupId>fr.ybo</groupId>
        <artifactId>moteurcsv</artifactId>
    </dependency>
</dependencies>

<repositories>
    <repository>
        <id>ybonnel-release</id>
        <url>https://repository-ybonnel.forge.cloudbees.com/release/</url>
    </repository>
</repositories>

Autre

Si vous n'êtes pas sous maven, il vous suffit d'intégrer les deux jars suivant :

Utilisation

Maintenant le vif du sujet, comment utiliser cette petite librairie.
Afin de pouvoir lire ou écrire un CSV il faut commencer par décrire la classe correspondante.
On va prendre pour l'exemple un CSV décrivant des personnes avec deux colonnes : "nom" et "prenom".
Voici un exemple correspondant :
nom,prenom
Bonnel,Yan
Vador,Dark
Noël,Père

Déclaration de la classe

Nous allons donc créer la classe Personne associée avec les annotations permettant de faire le mapping :

// Annotation permettant de dire au moteur que cette classe est associée à un fichier CSV.
@FichierCsv
public class Personne {

    // Annotation permettant de dire au moteur que cet attribut est mappé avec la colonne "nom" du CSV.
    @BaliseCsv("nom")
    private String nom;

    // Annotation permettant de dire au moteur que cet attribut est mappé avec la colonne "prenom" du CSV.
    @BaliseCsv("prenom")
    private String prenom;
}

Création du moteur

MoteurCsv moteur = new MoteurCsv(Personne.class);

Lecture d'un fichier CSV

Voici maintenant le code permettant de lire le fichier, et de le transformer en une liste d'objets :
InputStream stream = new FileInputStream(new File("personnes.csv"));
List<Personne> personnes = moteur.parseInputStream(stream, Personne.class);

Écriture d'un fichier CSV

Et le core permettant d'écrire un fichier :
Writer writer = new FileWriter(new File("personnes.csv"));
moteur.writeFile(writer, personnes, Personne.class);

Conclusion

J'espère que cette petite librairie sera utile à quelqu'un d'autre que moi :)
Elle est open-source (LGPL v3) : github.com/ybonnel/MoteurCsv
N'hésitez donc pas à forker et à faire des pull request!
Site généré contenant entre autre la javadoc : ybonnel.github.com/MoteurCsv

3 commentaires:

Unknown a dit…

Pour les fautes de frappes, c'est corrigé. Merci.

Pour le bench, je vais créer un projet à part pour voir, je ferais un autre billet. Ce qui serait intéressant c'est surtout de voir l'overhead par rapport à faire de l'open-csv pur.

Tu as des propositions pour les conditions du bench (taille de fichier, nombre de colonnes, type des colonnes, ...).

Unknown a dit…

@bbo Le moteur dispose bien d'un système d'adapter permettant de décoder de tout. Les adapter présents dans le moteur sont pour l'instant String, Boolean, Double, Integer. Il suffit de créer son propre adapter en implémentant l'interface AdapterCsv pour créer n'importe quel adapter.

Pour la couche de validation, c'est une très bonne idée, je vais y réfléchir, de même qu'un mécanisme permettant de rejeter des lignes tout en continuant à lire le fichier. Actuellement, en cas d'erreur le moteur s'arrête :)

Pour le bench, je devrait publier un billet dès ce soir :)

Thierry LER a dit…

A noter qu'on en parle ici : http://thierry-leriche-dessirier.developpez.com/tutoriels/java/charger-donnees-fichier-csv-5-min/#L6-C

Enregistrer un commentaire