API CSV per Java [chiuso]


164

Qualcuno può raccomandare una semplice API che mi permetterà di usare leggere un file di input CSV, fare alcune semplici trasformazioni e quindi scriverlo.

Un rapido google ha trovato http://flatpack.sourceforge.net/ che sembra promettente.

Volevo solo controllare cosa stanno usando gli altri prima di accoppiarmi a questa API.


Utilizzare il sito gemello Consigli Software Scambio di stack quando si richiedono suggerimenti su una libreria software. Ha diversi successi per Java e CSV .
Basil Bourque,

Risposte:


32

Apache Commons CSV

Dai un'occhiata ad Apache Common CSV .

Questa libreria legge e scrive diverse varianti di CSV , incluso quello standard RFC 4180 . Legge / scrive anche file delimitati da tabulazioni .

  • Eccellere
  • InformixUnload
  • InformixUnloadCsv
  • MySQL
  • Oracolo
  • PostgreSQLCsv
  • PostgreSQLText
  • RFC4180
  • TDF

Ho usato il CSV Commons sandbox per un po 'di tempo e non ho mai avuto problemi. Spero davvero che lo promuovano fino in fondo e lo tirino fuori dalla sandbox.
Alex Marshall,

3
@ bmatthews68 il link sandbox è defunto - sembra che sia stato spostato su apache commons correttamente (ho modificato anche il link nella risposta)
drevicko


83

Ho usato OpenCSV in passato.

import au.com.bytecode.opencsv.CSVReader;

String fileName = "data.csv";
CSVReader reader = new CSVReader (new FileReader (fileName));

// se la prima riga è l'intestazione String [] header = reader.readNext ();
// iterate su reader.readNext fino a quando non restituisce null String [] line = reader.readNext ();

C'erano alcune altre scelte nelle risposte a un'altra domanda .


Sfortunatamente, l'ultimo download di OpenCSV (v2.2 al momento del commento) non si compila e non fornisce un binario pre-costruito.
opyate

9
Il pacchetto che ho scaricato da SourceForge aveva un file binario nella cartella deploy.
Mike Sickler,

8
Se stai utilizzando Maven, tieni presente che il codice di dipendenza sul sito Web ufficiale contiene la dichiarazione di versione "2.0" che presenta alcuni bug, ma nei repository è stata aggiornata la versione 2.3.
broundee,

questa lib non scrive file in thread separati, no?
Ewoks,

3
secondo github.com/uniVocity/csv-parsers-comparison in media il 73% più lento di uniVocity ..
Ewoks

32

Aggiornamento: il codice in questa risposta è per Super CSV 1.52. Esempi di codice aggiornati per Super CSV 2.4.0 sono disponibili sul sito Web del progetto: http://super-csv.github.io/super-csv/index.html


Il progetto SuperCSV supporta direttamente l'analisi e la manipolazione strutturata delle cellule CSV. Da http://super-csv.github.io/super-csv/examples_reading.html troverai ad es.

dato un corso

public class UserBean {
    String username, password, street, town;
    int zip;

    public String getPassword() { return password; }
    public String getStreet() { return street; }
    public String getTown() { return town; }
    public String getUsername() { return username; }
    public int getZip() { return zip; }
    public void setPassword(String password) { this.password = password; }
    public void setStreet(String street) { this.street = street; }
    public void setTown(String town) { this.town = town; }
    public void setUsername(String username) { this.username = username; }
    public void setZip(int zip) { this.zip = zip; }
}

e che hai un file CSV con un'intestazione. Supponiamo il seguente contenuto

username, password,   date,        zip,  town
Klaus,    qwexyKiks,  17/1/2007,   1111, New York
Oufu,     bobilop,    10/10/2007,  4555, New York

È quindi possibile creare un'istanza di UserBean e popolarla con i valori della seconda riga del file con il seguente codice

class ReadingObjects {
  public static void main(String[] args) throws Exception{
    ICsvBeanReader inFile = new CsvBeanReader(new FileReader("foo.csv"), CsvPreference.EXCEL_PREFERENCE);
    try {
      final String[] header = inFile.getCSVHeader(true);
      UserBean user;
      while( (user = inFile.read(UserBean.class, header, processors)) != null) {
        System.out.println(user.getZip());
      }
    } finally {
      inFile.close();
    }
  }
}

utilizzando la seguente "specifica di manipolazione"

final CellProcessor[] processors = new CellProcessor[] {
    new Unique(new StrMinMax(5, 20)),
    new StrMinMax(8, 35),
    new ParseDate("dd/MM/yyyy"),
    new Optional(new ParseInt()),
    null
};

1
Il tuo codice non verrà compilato, quindi ho inviato alcune correzioni. Inoltre, ParseDate () non funziona correttamente, quindi l'ho sostituito per leggere una stringa. Può essere analizzato in seguito.

1
Grande limitazione: SuperCSV non è sicuro, sto andando a cercare Jackson, anche se potrebbe essere più limitato di funzionalità
ZiglioUK

Inoltre SuperCsv non consente l'utilizzo di multimappa. Sarebbe bello vederlo funzionare con MultiMaps.
Sid

19

Leggere la descrizione del formato CSV mi fa sentire che usare una libreria di terze parti sarebbe meno mal di testa che scriverlo da solo:

Wikipedia elenca 10 o qualcosa di noto librerie:

Ho confrontato le librerie elencate usando una specie di lista di controllo. OpenCSV mi è risultato vincitore (YMMV) con i seguenti risultati:

+ maven

+ maven - release version   // had some cryptic issues at _Hudson_ with snapshot references => prefer to be on a safe side

+ code examples

+ open source   // as in "can hack myself if needed"

+ understandable javadoc   // as opposed to eg javadocs of _genjava gj-csv_

+ compact API   // YAGNI (note *flatpack* seems to have much richer API than OpenCSV)

- reference to specification used   // I really like it when people can explain what they're doing

- reference to _RFC 4180_ support   // would qualify as simplest form of specification to me

- releases changelog   // absence is quite a pity, given how simple it'd be to get with maven-changes-plugin   // _flatpack_, for comparison, has quite helpful changelog

+ bug tracking

+ active   // as in "can submit a bug and expect a fixed release soon"

+ positive feedback   // Recommended By 51 users at sourceforge (as of now)

8

Usiamo JavaCSV , funziona abbastanza bene


3
L'unico problema con questa libreria è che non ti consentirà di produrre file CSV con terminatori di linea di Windows ( \r\n) quando non in esecuzione su Windows. L'autore non fornisce supporto da anni. Ho dovuto rovesciarlo
Mosty Mostacho,

6

Per l'ultima applicazione aziendale su cui ho lavorato per gestire una notevole quantità di CSV - un paio di mesi fa - ho usato SuperCSV su sourceforge e l'ho trovato semplice, robusto e privo di problemi.


+1 per SuperCSV, ma ha alcuni bug cattivi che non sono ancora stati corretti, i nuovi bug non sono attualmente gestiti e l'ultima versione ha quasi due anni. Ma stiamo usando una versione modificata / modificata in produzione senza problemi.
MRalwasser,

2
@MRalwasser Super CSV 2.0.0-beta-1 è stato recentemente rilasciato. Include molte correzioni di bug e nuove funzionalità (incluso il supporto Maven e una nuova estensione Dozer per la mappatura di proprietà e array / raccolte nidificate)
James Bassett,

1
@ Hound-Dog Grazie per l'aggiornamento, ho già notato la nuova beta e sono contento di vedere vivo il progetto - anche se la frequenza degli commit mi fa ancora un po 'paura (quasi tutti si impegnano solo in pochi giorni). Ma darò un'occhiata. Esiste una data di rilascio stimata dell'ultimo 2.0?
MRalwasser,

2
@MRalwasser Al momento sono l'unico sviluppatore e ho un lavoro a tempo pieno, quindi tendo a lavorare su questo ogni volta che ottengo un fine settimana gratuito - quindi lo sporadico si impegna :) Quasi 1000 download SF della beta ora e nessun bug, quindi cerco una versione definitiva all'inizio del prossimo mese. Se hai idee per funzionalità future, faccelo sapere.
James Bassett,

1
SuperCSV non è thread-safe in questa fase, il che lo rende non molto robusto imho
ZiglioUK

5

Puoi usare csvreader api e scaricare dalla seguente posizione:

http://sourceforge.net/projects/javacsv/files/JavaCsv/JavaCsv%202.1/javacsv2.1.zip/download

o

http://sourceforge.net/projects/javacsv/

Usa il seguente codice:

/ ************ For Reading ***************/

import java.io.FileNotFoundException;
import java.io.IOException;

import com.csvreader.CsvReader;

public class CsvReaderExample {

    public static void main(String[] args) {
        try {

            CsvReader products = new CsvReader("products.csv");

            products.readHeaders();

            while (products.readRecord())
            {
                String productID = products.get("ProductID");
                String productName = products.get("ProductName");
                String supplierID = products.get("SupplierID");
                String categoryID = products.get("CategoryID");
                String quantityPerUnit = products.get("QuantityPerUnit");
                String unitPrice = products.get("UnitPrice");
                String unitsInStock = products.get("UnitsInStock");
                String unitsOnOrder = products.get("UnitsOnOrder");
                String reorderLevel = products.get("ReorderLevel");
                String discontinued = products.get("Discontinued");

                // perform program logic here
                System.out.println(productID + ":" + productName);
            }

            products.close();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

}

Scrivi / Aggiungi al file CSV

Codice:

/************* For Writing ***************************/

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

import com.csvreader.CsvWriter;

public class CsvWriterAppendExample {

    public static void main(String[] args) {

        String outputFile = "users.csv";

        // before we open the file check to see if it already exists
        boolean alreadyExists = new File(outputFile).exists();

        try {
            // use FileWriter constructor that specifies open for appending
            CsvWriter csvOutput = new CsvWriter(new FileWriter(outputFile, true), ',');

            // if the file didn't already exist then we need to write out the header line
            if (!alreadyExists)
            {
                csvOutput.write("id");
                csvOutput.write("name");
                csvOutput.endRecord();
            }
            // else assume that the file already has the correct header line

            // write out a few records
            csvOutput.write("1");
            csvOutput.write("Bruce");
            csvOutput.endRecord();

            csvOutput.write("2");
            csvOutput.write("John");
            csvOutput.endRecord();

            csvOutput.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}


2

Il formato CSV sembra abbastanza facile per StringTokenizer ma può diventare più complicato. Qui in Germania viene utilizzato un punto e virgola come delimitatore e le celle contenenti delimitatori devono essere salvate. Non lo gestirai facilmente con StringTokenizer.

Vorrei andare su http://sourceforge.net/projects/javacsv


0

Se hai intenzione di leggere CSV da Excel, ci sono alcuni casi d'angolo interessanti. Non riesco a ricordarli tutti, ma l'apache commons csv non era in grado di gestirlo correttamente (con, ad esempio, url).

Assicurati di testare l'output di Excel con virgolette, virgole e barre in tutto il luogo.


La libreria CSV di Apache Commons offre una variante specifica per Microsoft Excel . Non so se questo ora gestisce i problemi che menzioni o meno.
Basil Bourque,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.