1. Introduction▲
Dans ce document, nous allons voir comment charger des données depuis un fichier CSV simple à l'aide de la bibliothèque Open-CSVOpen-CSV (et MoteurCsv en annexe), puis transformer ces données en objets de notre modèle.
Open-CSV est une bibliothèque gratuite, écrite en Java, qui simplifie la lecture complexe des fichiers CSV.
1-A. À propos▲
Découvrir une technologie n'est pas chose facile. En aborder plusieurs d'un coup l'est encore moins. Partant de ce constat, cet article a été écrit pour aller à l'essentiel. Les points importants sont présentés dans le corps de l'article et les éléments secondaires sont expliqués en annexe.
1-B. Avant de commencer▲
Pour écrire ce tutoriel, j'ai utilisé les éléments suivants :
- Java JDK 1.6.0_24-b07 ;
- Eclipse Indigo 3.7 JEE 64b ;
- Maven 3.0.3.
Ce tutoriel s'inspire très largement de mon article sur la lecture des fichiers CSV en JavaLes fichier CSV en Java. Ce tutoriel reprend également les objets utilisés dans les articles « Afficher un tableau avec un Table Model Swing en 5 minutes » et « Afficher un graphe jfreechart en 5 minutes ». Même si elle est conseillée, la lecture de ces articles n'est pas indispensable pour la suite.
1-C. Mise à jour▲
27 février 2012 : Ajout d'un exemple d'utilisation de la lib MoteurCsv (en annexe).
12 juillet 2012 : Prise en compte de la nouvelle version de la lib MoteurCSV (en annexe).
2. Découverte du modèle d'exemple▲
2-A. Télécharger, installer et importer le projet d'exemple▲
Pour commencer, je vous propose de télécharger le fichier Zip « notes3_domain.zip », contenant un projet Java-Maven d'exemple.
Compilez le projet d'exemple et importez-le dans Eclipse (comme expliqué dans le tutoriel « Importer un projet Maven dans Eclipse en 5 minutes ») ou dans l'IDE de votre choix.
Pour suivre ce tutoriel, vous pouvez vous contenter de lire les codes proposés ci-dessous (codes complets en annexe).
2-B. Les objets du modèle▲
Le projet d'exemple reprend les objets utilisés dans les tutoriels cités plus haut, et dont l'objectif est de modéliser (et d'afficher) les notes d'un groupe d'élèves au dernier examen.
Sans ordre, le modèle est composé des objets suivants.
package com.thi.notes.domain;
public enum Sexe {
    HOMME("Garçon"),
    FEMME("Fille");
    private final String label;
    Sexe(String label) {
        this.label = label;
    }
    public String getLabel() {
        return label;
    }
}package com.thi.notes.domain;
public class Eleve {
    private String nom;
    private String prenom;
    private Integer annee;
    private Sexe sexe;
    public Eleve(String nom, String prenom, Integer annee, Sexe sexe) {
        ...
    }
    // + getter-setter
}package com.thi.notes.domain;
public class NoteEleve {
    private Eleve eleve;
    private Double note;
    public NoteEleve(Eleve eleve, Double note) {
        ...
    }
    // + getter-setter
}Sans surprise, la classe Eleve représente une personne, et plus spécifiquement un élève. La classe NoteEleve est un « wrapper » qui possède un objet Eleve et une note (sur 20) associée. Quant à l'enum Sexe, son rôle dans l'histoire est évident.
2-C. Les données à lire▲
Dans ce tutoriel, nous allons utiliser deux fichiers CSV. Le premier, nommé « eleves.csv », contient la liste des élèves. Le second, nommé « notes-dernier-exam.csv », contient quant à lui les notes desdits élèves au dernier examen.
Dans un fichier CSV, les données sont séparées par des virgules, ou un point-virgule pour le format CSV français standard.
# Nom;Prénom;Classe;Sexe;Date de naissance;Adresse
Durand;Marie;3;F;02/01/1992;15 rue du Lac 75001 Paris
Alesi;Julie;3;F;08/01/1992;72 av. Jean Dupont 75003 Paris
Martini;Carine;3;F;17/01/1992;2 rue du Moulin 92230 Neullavy
Varola;Sophie;3;F;21/01/1992;15 rue du Lac 75001 Paris
Labiche;Lelou;3;F;21/01/1992;15 rue du Lac 75001 Paris
Dujardin;Anne;3;F;03/02/1992;67 rue des Jardins 91800 Brunoy
Laventure;Martine;3;F;15/02/1992;15 rue du Lac 75001 Paris
...
Fivolini;Kevin;3;H;06/12/1992;15 rue du Lac 75001 Paris
Laferme;Martin;3;H;07/12/1992;15 rue du Lac 75001 Paris
Dupuis;Vincent;3;H;15/12/1992;15 rue du Lac 75001 Paris
Lagrange;Alexandre;3;H;28/12/1992;15 rue du Lac 75001 ParisOn constate que de nombreux élèves habitent au « 15 rue du Lac ». Cette adresse est celle de la résidence universitaire de l'école.
# Nom;Prénom;Note
Durand;Marie;5
Alesi;Julie;8
Martini;Carine;10,5
Varola;Sophie;12
Labiche;Lelou;12
Dujardin;Anne;13
Laventure;Martine;14
...
Fivolini;Kevin;19
Laferme;Martin;20
Dupuis;Vincent;20On remarque que « Alexandre Lagrange », que j'ai mis en fin de fichier pour simplifier la lecture, n'a pas de note au dernier examen ; il était absent. Dans ce tutoriel, nous dirons qu'une absence vaut un zéro. Il faudra donc gérer ce cas.
3. Action▲
3-A. Compléter le modèle▲
Durée estimée : 30 secondes.
Pour commencer, on doit ajouter les attributs « date de naissance » et « adresse », qui ne sont pas encore dans « Eleve.java » et modifier le constructeur de la classe en conséquence.
public class Eleve {
    private String nom;
    private String prenom;
    private Integer annee;
    private Sexe sexe;
    private Date dateNaissance;
    private String adresse;
    public Eleve(String nom, String prenom, Integer annee, Sexe sexe, Date dateNaissance, String adresse) {
        ...
    }
    // + getter-setter
    ...
}3-B. Créer des DAO vides▲
Durée estimée : 1 minute.
Nous allons créer deux DAO vides : un pour charger la liste des élèves et l'autre pour charger les notes. Chaque DAO ne renvoie qu'une partie des informations disponibles. Nous verrons dans un prochain tutoriel comment réconcilier les données, ce qui n'est pas le sujet ici.
package com.thi.notes.dao;
import java.util.Map;
public class NoteDao {
    public Map<String, Double> findNotesDernierExam() {
        return null;
    }
}Ce DAO (Data Access Object) renvoie une « Map » dont les clés sont les noms (prénom + nom) des élèves et les valeurs sont les notes obtenues au dernier examen.
package com.thi.notes.dao;
import java.util.List;
import com.thi.notes.domain.Eleve;
public class EleveDao {
    public List<Eleve> findEleves() {
        return null;
    }
}Ce DAO renvoie la liste des élèves, tout simplement, en utilisant les objets Eleve et Sexe. Pour lire les données à l'aide de EleveDao, on utilisera un code ressemblant au suivant.
final EleveDao eleveDao = new EleveDao();
final List<Eleve> eleves = eleveDao.findEleves();
for(Eleve eleve : eleves) {
    System.out.println(eleve);
}Dans la suite de ce tutoriel, nous allons nous concentrer sur « EleveDao.java », l'autre DAO utilisant globalement les mêmes principes. Un code d'exemple est toutefois proposé en annexe et dans le fichier Zip final.
3-C. Ajout d'Open-CSV▲
Durée estimée : 30 secondes.
Pour utiliser Open CSV dans un projet Java-Maven, il suffit d'ajouter une dépendance dans le « pom.xml ».
<dependency>
    <groupId>net.sf.opencsv</groupId>
    <artifactId>opencsv</artifactId>
    <version>2.3</version>
</dependency>Puis, comme d'habitude, il faut relancer une installation Maven.
mvn clean install eclipse:eclipseEn fonction des éléments déjà présents sur l'ordinateur, la réponse de Maven devrait ressembler à la trace suivante.
C:\dvp\notes>mvn clean install eclipse:eclipse
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Notes 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.4.1:clean (default-clean) @ notes ---
[INFO] Deleting C:\dvp\notes\target
[INFO]
[INFO] --- maven-resources-plugin:2.4.3:resources (default-resources) @ notes ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 2 resources
[INFO]
[INFO] --- maven-compiler-plugin:2.3.2:compile (default-compile) @ notes ---
[INFO] Compiling 9 source files to C:\dvp\notes\target\classes
[INFO]
[INFO] --- maven-resources-plugin:2.4.3:testResources (default-testResources) @ notes ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 0 resource
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 10.197s
[INFO] Finished at: Wed Jan 18 20:19:12 CET 2012
[INFO] Final Memory: 12M/59M3-D. Lecture des données▲
Durée estimée : 3 minutes.
On entre dans le vif du sujet. Comme indiqué plus haut, nous allons nous concentrer sur la lecture de la liste d'élèves.
Pour commencer, il faut accéder au fichier CSV.
public class EleveDao {
    private final static String RESOURCES_PATH = "src/main/resources/";
    private final static String ELEVES_FILE_NAME = "eleves.csv";
    public List<Eleve> findEleves() {
        File file = new File(RESOURCES_PATH + ELEVES_FILE_NAME);
        FileReader fr = new FileReader(file);
        ...
    }
}Puis j'utilise l'objet « CSVReader » fourni par la bibliothèque « Open-CSV ».
public class EleveDao {
    private final static char SEPARATOR = ';';
    ...
    public List<Eleve> findEleves() {
        File file = new File(RESOURCES_PATH + ELEVES_FILE_NAME);
        FileReader fr = new FileReader(file);
        CSVReader csvReader = new CSVReader(fr, SEPARATOR);
        ...Ce « reader » nous permet de lire les données du fichier.
List<String[] > data = new ArrayList<String[] >();
String[] nextLine = null;
while ((nextLine = csvReader.readNext()) != null) {
    int size = nextLine.length;
    // ligne vide
    if (size == 0) {
        continue;
    }
    String debut = nextLine[0].trim();
    if (debut.length() == 0 && size == 1) {
        continue;
    }
    // ligne de commentaire
    if (debut.startsWith("#")) {
        continue;
    }
    data.add(nextLine);
}Il ne reste plus qu'à transformer les données, qu'on a sous forme de tableau de String, en objets Eleve.
List<String[] > data = new ArrayList<String[] >();
...
List<Eleve> eleves = new ArrayList<Eleve>();
DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
for (String[] oneData : data) {
    String nom = oneData[0];
    String prenom = oneData[1];
    String classeStr = oneData[2];
    String sexeStr = oneData[3];
    String dateNaissanceStr = oneData[4];
    String adresse = oneData[5];
    Integer classe = Integer.parseInt(classeStr);
    Sexe sexe = (sexeStr.equalsIgnoreCase("F")) ? FEMME : HOMME;
    Date dateNaissance = dateFormat.parse(dateNaissanceStr);
    Eleve eleve = new Eleve(nom, prenom, classe, sexe, dateNaissance, adresse);
    eleves.add(eleve);
}
return eleves;Ici, la seule petite difficulté vient de la transformation de la date de naissance, d'un String vers un objet Date, ce que l'on fait à l'aide des classes Java « DateFormat » et « SimpleDateFormat ».
DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
String dateNaissanceStr = "28/01/1992"; // Par exemple
Date dateNaissance = dateFormat.parse(dateNaissanceStr);Le tutoriel « fichiers CSV en Java » propose une façon plus élégante de transformer les lignes du fichier en liste d'objets.
Il ne reste plus qu'à réorganiser un peu le code (pour éviter d'avoir des méthodes trop grosses) et à factoriser les traitements (et ainsi ne pas dupliquer de code dans l'autre DAO). Le code final, avec ces changements, est disponible en annexe.
4. Conclusions▲
Comme on vient de le constater, il est relativement simple de lire un fichier CSV à l'aide d'une bibliothèque telle que Open-CSV. Cette dernière réalise un ensemble de traitements complexes et en masque la complexité. Il existe d'autres bibliothèques sur le marché, qui fonctionnent différemment et que je vous invite à regarder, au moins pas curiosité.
Et bien entendu, je vous encourage à lire mon tutoriel sur les fichiers CSV en JavaLes fichier CSV en Java.
Le code final de ce tutoriel est disponible dans le fichier ZIP notes4_domain-et-dao-csv.zip.code final
Retrouvez les tutoriels de la série « en 5 minutes » sur developpez.com à l'adresse https://thierry-leriche-dessirier.developpez.com/#page_articlesEn 5 minutes.
5. Remerciements▲
Je tiens à remercier, en tant qu'auteur de tutoriel rapide, toutes les personnes qui m'ont aidé et soutenu. Je pense tout d'abord à mes collègues qui subissent mes questions au quotidien, mais aussi à mes contacts et amis du Web, dans le domaine de l'informatique ou non, qui m'ont fait part de leurs remarques et critiques. Bien entendu, je n'oublie pas l'équipe de developpez.com qui m'a guidé dans la rédaction de cet article et m'a aidé à le corriger et le faire évoluer, principalement sur le forum.
Plus particulièrement j'adresse mes remerciements, à Claude LELOUP (ClaudeLELOUP), Mickael BARON (keulkeul), Nemek et Yan BONNEL.

6. Annexes▲
6-A. Liens▲
Le site Web d'Open-CSV est disponible à l'adresse 
http://opencsv.sourceforge.net
Pour suivre cet article, je conseille la lecture des tutoriels 
		« Importer un projet Maven dans Eclipse en 5 minutes » disponible à l'adresse 
https://thierry-leriche-dessirier.developpez.com/tutoriels/java/importer-projet-maven-dans-eclipse-5-minImporter un projet Maven dans Eclipse en 5 minutes
		Je vous encourage à lire mon tutoriel sur les fichiers CSV en Java, disponible à l'adresse 
https://thierry-leriche-dessirier.developpez.com/tutoriels/java/csv-avec-javaLes fichier CSV en Java
6-B. Les fichiers importants en entier▲
package com.thi.notes.dao;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import au.com.bytecode.opencsv.CSVReader;
public class CsvFileHelper {
    public static List<String[] > readCsvFile(String fileName, char separator) {
        final List<String[] > data = new ArrayList<String[] >();
        try {
            final File file = new File(fileName);
            final FileReader fr = new FileReader(file);
            final CSVReader csvReader = new CSVReader(fr, separator);
            String[] nextLine = null;
            while ((nextLine = csvReader.readNext()) != null) {
                final int size = nextLine.length;
                // ligne vide
                if (size == 0) {
                    continue;
                }
                final String debut = nextLine[0].trim();
                if (debut.length() == 0 && size == 1) {
                    continue;
                }
                // ligne de commentaire
                if (debut.startsWith("#")) {
                    continue;
                }
                data.add(nextLine);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return data;
    }
}package com.thi.notes.dao;
import java.util.List;
import com.thi.notes.domain.Eleve;
public interface EleveDao {
    List<Eleve> findEleves();
}package com.thi.notes.dao;
import static com.thi.notes.dao.CsvFileHelper.readCsvFile;
import static com.thi.notes.domain.Sexe.FEMME;
import static com.thi.notes.domain.Sexe.HOMME;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import com.thi.notes.domain.Eleve;
import com.thi.notes.domain.Sexe;
public class CsvEleveDao implements EleveDao {
    private final static char SEPARATOR = ';';
    private final static String RESOURCES_PATH = "src/main/resources/";
    private final static String ELEVES_FILE_NAME = "eleves.csv";
    @Override
    public List<Eleve> findEleves() {
        final List<String[] > data = readCsvFile(RESOURCES_PATH + ELEVES_FILE_NAME, SEPARATOR);
        final List<Eleve> eleves = dataToEleves(data);
        return eleves;
    }
    private List<Eleve> dataToEleves(List<String[] > data) {
        final List<Eleve> eleves = new ArrayList<Eleve>();
        try {
            final DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
            for (String[] oneData : data) {
                final String nom = oneData[0];
                final String prenom = oneData[1];
                final String classeStr = oneData[2];
                final String sexeStr = oneData[3];
                final String dateNaissanceStr = oneData[4];
                final String adresse = oneData[5];
                final Integer classe = Integer.parseInt(classeStr);
                final Sexe sexe = (sexeStr.equalsIgnoreCase("F")) ? FEMME : HOMME;
                final Date dateNaissance = dateFormat.parse(dateNaissanceStr);
                final Eleve eleve = new Eleve(nom, prenom, classe, sexe, dateNaissance, adresse);
                eleves.add(eleve);
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return eleves;
    }
}Dans un prochain tutoriel, je vous montrerai comment charger la liste d'élèves à partir d'une base de données MySql, et non plus à partir d'un fichier CSV. Néanmoins, la signature de la méthode findEleves ne devrait pas changer. C'est pourquoi j'ai ajouté une interface. Comme vous pouvez le deviner, de la même manière que CsvEleveDao implémente EleveDao, le prochain tutoriel introduira l'implémentation DatabaseEleveDao de EleveDao pour lire les données depuis la base.
package com.thi.notes.dao;
import java.util.Map;
public interface NoteDao {
     Map<String, Double> findNotesDernierExam();
}package com.thi.notes.dao;
import static com.thi.notes.dao.CsvFileHelper.readCsvFile;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class CsvNoteDao implements NoteDao {
    private final static char SEPARATOR = ';';
    private final static String RESOURCES_PATH = "src/main/resources/";
    private final static String ELEVES_FILE_NAME = "notes-dernier-exam.csv";
    @Override
    public Map<String, Double> findNotesDernierExam() {
        final List<String[] > data = readCsvFile(RESOURCES_PATH + ELEVES_FILE_NAME, SEPARATOR);
        final Map<String, Double> map = dataToMap(data);
        return map;
    }
    private Map<String, Double> dataToMap(List<String[] > data) {
        final Map<String, Double> map = new HashMap<String, Double>();
        for (String[] oneData : data) {
            final String nom = oneData[0];
            final String prenom = oneData[1];
            final String noteStr = oneData[2];
            final Double note = new Double(noteStr.replace(",", "."));
            map.put(nom + " " + prenom, note);
        }
        return map;
    }
}package com.thi.notes;
import java.util.List;
import java.util.Map;
import com.thi.notes.dao.CsvEleveDao;
import com.thi.notes.dao.CsvNoteDao;
import com.thi.notes.dao.EleveDao;
import com.thi.notes.dao.NoteDao;
import com.thi.notes.domain.Eleve;
public class DaoLauncher {
    public static void main(String[] args) {
        final EleveDao eleveDao = new CsvEleveDao();
        final List<Eleve> eleves = eleveDao.findEleves();
        System.out.println("Liste des eleves");
        for (Eleve eleve : eleves) {
            System.out.println(eleve);
        }
        final NoteDao noteDao = new CsvNoteDao();
        final Map<String, Double> notes = noteDao.findNotesDernierExam();
        System.out.println("Notes des eleves");
        for (String key : notes.keySet()) {
            final Double note = notes.get(key);
            System.out.println(key + " : " + note);
        }
    }
}6-C. Utilisation de la lib MoteurCsv▲
Comme me l'a proposé Yan BonnelBlog de Yan Bonnel, j'ai adapté le code présenté ci-dessus pour employer la bibliothèque MoteurCsvPage du projet MoteurCsv, qui ressemble un peu à JPA dans son utilisation.
Tout d'abord, je change mon pom.xml, sachant que MoteurCsv possède déjà une dépendance vers OpenCSV.
<!-- MoteurCSV -->
<dependency>
    <groupId>fr.ybo</groupId>
    <artifactId>moteurcsv</artifactId>
    <version>1.1.3</version>
</dependency><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.thi</groupId>
    <artifactId>notes-avec-moteurcsv</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    ...
    <developers>
        <!-- Thierry -->
        <developer><name>Thierry Leriche-Dessirier</name></developer>
        <!-- Yan -->
        <developer><name>Yan Bonnel</name></developer>
    </developers>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <junit.version>4.8.2</junit.version>
        <jfreechart.version>1.0.14</jfreechart.version>
        
        <!-- Remplacement de opencsv par moteurcsv -->
        <!--<opencsv.version>2.3</opencsv.version>-->
        <moteurcsv.version>1.1.3</moteurcsv.version>
    </properties>
    <dependencyManagement>
        <dependencies>
            ...
            <!-- Open CSV -->
            <!--<dependency>
                <groupId>net.sf.opencsv</groupId>
                <artifactId>opencsv</artifactId>
                <version>${opencsv.version}</version>
            </dependency>-->
            
            <!-- MoteurCSV -->
            <dependency>
                <groupId>fr.ybo</groupId>
                <artifactId>moteurcsv</artifactId>
                <version>${moteurcsv.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        ...
        <!-- Open CSV -->
        <!--<dependency>
            <groupId>net.sf.opencsv</groupId>
            <artifactId>opencsv</artifactId>
        </dependency>-->
        
        <!-- MoteurCSV -->
        <dependency>
            <groupId>fr.ybo</groupId>
            <artifactId>moteurcsv</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                    <encoding>UTF-8</encoding>
                    <source>1.6</source>
                    <target>1.6</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <repositories>
        <repository>
            <id>ybonnel-release</id>
            <url>https://repository-ybonnel.forge.cloudbees.com/release/</url>
        </repository>
    </repositories>
</project>Je vais ensuite modifier mes beans pour que ça ressemble à du JPA.
@FichierCsv(separateur = ";")
public class Eleve {
    // private String nom;
    // private String prenom;
    // private Integer annee;
    // private Sexe sexe;
    // private Date dateNaissance;
    // private String adresse;
    @BaliseCsv("Nom")
    private String nom;
    @BaliseCsv("Prénom")
    private String prenom;
    @BaliseCsv(value = "Classe", adapter = AdapterInteger.class)
    private Integer annee;
    @BaliseCsv(value = "Sexe", adapter = AdapterSexe.class)
    private Sexe sexe;
    @BaliseCsv(value = "Date de naissance", adapter = AdapterDate.class)
    private Date dateNaissance;
    @BaliseCsv(value = "Adresse")
    private String adresse;
    public Eleve() {
        // Constructeur par defaut obligatoire pour MoteurCsv.
    }
    
    ...public enum Sexe {
    
    HOMME("Garçon"),
    FEMME("Fille");
    private final String label;
    Sexe(String label) {
        this.label = label;
    }
    public String getLabel() {
        return label;
    }
    public static class AdapterSexe implements AdapterCsv<Sexe> {
        @Override
        public Sexe parse(String chaine) {
            return (chaine.equalsIgnoreCase("F")) ? FEMME : HOMME;
        }
        @Override
        public String toString(Sexe objet) {
            return objet == FEMME ? "F" : "H";
        }
    }
}Je peux maintenant passer à la lecture du fichier.
public class CsvEleveDao implements EleveDao {
    private final static char SEPARATOR = ';';
    private final static String RESOURCES_PATH = "src/main/resources/";
    private final static String ELEVES_FILE_NAME = "eleves.csv";
    // Moteur CSV
    private final static MoteurCsv moteurCsv = new MoteurCsv(Eleve.class);
    @Override
    public List<Eleve> findEleves() {
        // final List<String[] > data = readCsvFile(RESOURCES_PATH +
        // ELEVES_FILE_NAME, SEPARATOR);
        // final List<Eleve> eleves = dataToEleves(data);
        List<Eleve> eleves = null;
        try {
            eleves = moteurCsv.parseInputStream(new FileInputStream(new File(RESOURCES_PATH + ELEVES_FILE_NAME)), Eleve.class);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            eleves = new ArrayList<Eleve>();
        }
        return eleves;
    }
    
    public static class AdapterDate implements AdapterCsv<Date> {
        final DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
        @Override
        public Date parse(String chaine) {
            try {
                return dateFormat.parse(chaine);
            } catch (ParseException e) {
                return null;
            }
        }
        @Override
        public String toString(Date objet) {
            return dateFormat.format(objet);
        }
    }Ici, je ne m'occupe que de la liste des élèves. Pour lire l'autre fichier, il faut faire la même chose.
Petit détail qui compte, MoteurCsv a besoin, par défaut, que la première ligne importante contienne les noms des champs, puisqu'ils sont utilisés pour « mapper » les objets.
Nom;Prénom;Classe;Sexe;Date de naissance;Adresse
Durand;Marie;3;F;02/01/1992;15 rue du Lac 75001 Paris
Alesi;Julie;3;F;08/01/1992;72 av. Jean Dupont 75003 Paris
Martini;Carine;3;F;17/01/1992;2 rue du Moulin 92230 Neullavy
...Et voilà… C'est encore plus simple.
Le code final de ce tutoriel, incluant l'utilisation de MoteurCsv est disponible dans le fichier ZIP notes4_moteurcsv.zip.code final
6-C-1. Version 1.2.0 de la lib▲
Mise à jour : 12 juillet 2012.
Les nouvelles versions de la lib MoteurCsv (par exemple la version 1.2.0) s'utilisent d'une autre manière que ce qui est présenté ci-dessus. La méthode « parseInputStream() » renvoie désormais un objet de type « Resultat » et non plus la liste des objets lus.
public class CsvEleveDao implements EleveDao {
    private final static char SEPARATOR = ';';
    private final static String RESOURCES_PATH = "src/main/resources/";
    private final static String ELEVES_FILE_NAME = "eleves.csv";
    // Moteur CSV
    private final static MoteurCsv moteurCsv = new MoteurCsv(Eleve.class);
    @Override
    public List<Eleve> findEleves() {
        
        Resultat<Eleve> resultat =  moteurCsv.parseInputStream(new FileInputStream(new File(RESOURCES_PATH + ELEVES_FILE_NAME)), Eleve.class);
        List<Eleve> eleves = resultat.getObjets();Cet objet « Resultat » propose la méthode « getErreurs() » qui montre les éventuelles erreurs qui sont arrivées durant les traitements.
En plus de ce changement, la lib propose une nouvelle syntaxe (prog fonc) qui fera un peu penser à celle utilisée dans Guava. Elle permet de traiter les éléments trouvés directement.
public class CsvEleveDao implements EleveDao {
    final MoteurCsv moteurCsv = new MoteurCsv(Eleve.class);
    ...
    @Override
    public List<Eleve> findEleves() {
    
        final File f = new File(RESOURCES_PATH + ELEVES_FILE_NAME);
        final FileReader fr = new FileReader(f);
        
        final List<Eleve> eleves = newArrayList(); // Static factory Guava
        moteurCsv.parseFileAndInsert(fr, Eleve.class, new InsertObject<Eleve>() {
            @Override
            public void insertObject(Eleve eleve) {
                foo(eleve); // Faire un truc sur l'eleve.
                ...
                result.add(eleve); // Mettre dans la liste, si besoin.
                ...
                System.out.println(eleve); // Un petit sysout pour le plaisir.
            }
        });
 ♪
 ♪






