web-dev-qa-db-fra.com

API Java permettant de créer un objet à partir d'un fichier CSV

Je cherche une bibliothèque qui me permette de mapper un contenu .csv à un objet.

Quelque chose comme:

public class Person {

    private String name;
    private int age;

    @CsvField("name")
    public String getName() {
        return this.name;
    }

    @CsvField("age")
    public int getAge() {
        return this.age;
    }
}

et ensuite dire quelque chose comme:

final Person filledWithDataFromCsv = csvApi.load(csvFilepath, Person.class);

à partir du CSV donné:

#name, age
tom, 11
jim, 32

Est-ce que quelqu'un sait d'une telle API, ou une qui fait quelque chose de similaire. Je ne veux pas que les annotations soient indispensables, je veux simplement pouvoir charger le fichier avec une ligne de code et une classe prédéfinie.

24
Simeon

JSefa vous permet d'annoter les classes Java pouvant être utilisées dans un processus de sérialisation et de désérialisation. Le tutorial montre comment cela fonctionne avec la classe CsvIOFactory.

(Extrait du didacticiel) Annoter un bean est aussi simple que de spécifier les emplacements des éléments dans la liste de valeurs et, si nécessaire, vous devrez spécifier le format de conversion:

@CsvDataType()
public class Person {
    @CsvField(pos = 1)
    String name;

    @CsvField(pos = 2, format = "dd.MM.yyyy")
    Date   birthDate;
}
22
Vineet Reynolds

Vous ne pouvez pas vous tromper avec uniVocity-parsers . Il supporte toutes sortes d'opérations puissantes et il est beaucoup plus rapide que tout autre analyseur CSV pour Java.

Voici une classe avec quelques exemples:

class TestBean {

    // if the value parsed in the quantity column is "?" or "-", it will be replaced by null.
    @NullString(nulls = { "?", "-" })
    // if a value resolves to null, it will be converted to the String "0".
    @Parsed(defaultNullRead = "0")
    private Integer quantity;   // The attribute type defines which conversion will be executed when processing the value.

    @Trim
    @LowerCase
    // the value for the comments attribute is in the column at index 4 (0 is the first column, so this means fifth column in the file)
    @Parsed(index = 4)
    private String comments;

    // you can also explicitly give the name of a column in the file.
    @Parsed(field = "amount")
    private BigDecimal amount;

    @Trim
    @LowerCase
    // values "no", "n" and "null" will be converted to false; values "yes" and "y" will be converted to true
    @BooleanString(falseStrings = { "no", "n", "null" }, trueStrings = { "yes", "y" })
    @Parsed
    private Boolean pending;
}

Voici comment obtenir une liste de TestBean

BeanListProcessor<TestBean> rowProcessor = new BeanListProcessor<TestBean>(TestBean.class);

CsvParserSettings parserSettings = new CsvParserSettings();
parserSettings.setRowProcessor(rowProcessor);
parserSettings.setHeaderExtractionEnabled(true);

CsvParser parser = new CsvParser(parserSettings);
parser.parse(getReader("/examples/bean_test.csv"));

List<TestBean> beans = rowProcessor.getBeans();

Divulgation: Je suis l'auteur de cette bibliothèque. Il est open-source et gratuit (licence Apache V2.0).

9
Jeronimo Backes

Je préfère opencsv, c'est ultra simple et très propre.

http://opencsv.sourceforge.net/

Par exemple en lisant:

CSVReader reader = new CSVReader(new FileReader("yourfile.csv"));
String [] nextLine;
while ((nextLine = reader.readNext()) != null) {
    // nextLine[] is an array of values from the line
    System.out.println(nextLine[0] + nextLine[1] + "etc...");
}
7
Thomas Jungblut

Il existe de très bonnes implémentations JDBC pour CSV. Vous pouvez donc utiliser un tel pilote, configurer une source de données pour l'utiliser, puis utiliser JPA (ou autre) pour le mappage objet-relationnel au-dessus de cette source de données.

3
Costi Ciudatu

la dernière version de https://github.com/arnaudroger/SimpleFlatMapper 0.9.4 a maintenant un CsvMapper. Il utilise l'en-tête pour faire correspondre le nom de la propriété ou, si aucun en-tête, vous pouvez spécifier le nom de la colonne via le générateur . Il prend en charge l'injection de constructeur, de définition et de champ. Lisez à partir de InputStream ou de Reader . De plus, il ne gérerait pas le mappage de #name à name. y a-t-il une raison pour laquelle il y a un # au début du csv?

public class MyParser {
    private final CsvMapper<MyObject> mapper = 
           CsvMapperFactory.newInstance().newMapper(MyObject.class);
    public void writeAllObjectToLambda(Writer writer, InputStream is) throws IOException {
        mapper.forEach(is, (o) -> writer.append(o.toString()).append("\n"));
    }
}
1
user3996996