API CSV para Java [fechada]

164

Alguém pode recomendar uma API simples que me permita usar ler um arquivo de entrada CSV, fazer algumas transformações simples e depois gravá-lo.

Um rápido google encontrou http://flatpack.sourceforge.net/ que parece promissor.

Eu só queria verificar o que os outros estão usando antes de me associar a essa API.

David Turner
fonte
Use o site da irmã Recomendações de Software Stack Exchange ao pedir sugestões em uma biblioteca de software. Possui vários hits para Java e CSV .
Basil Bourque

Respostas:

32

Apache Commons CSV

Confira o Apache Common CSV .

Esta biblioteca lê e grava várias variações de CSV , incluindo a RFC 4180 padrão . Também lê / grava arquivos delimitados por tabulação .

  • Excel
  • InformixUnload
  • InformixUnloadCsv
  • MySQL
  • Oráculo
  • PostgreSQLCsv
  • PostgreSQLText
  • RFC4180
  • TDF
Basil Bourque
fonte
Eu uso o CSV do Commons na área de proteção há algum tempo e nunca tive um problema. Eu realmente espero que eles o promovam em pé e tirem da caixa de areia.
Alex Marshall
3
@ bmatthews68 o link sandbox é extinta - Parece que é movido para Apache Commons adequada (eu editei o link na resposta também)
drevicko
Exemplos do Apache Commons aqui: apisonar.com/java-examples/org.apache.commons.csv.html
APISonar
83

Eu usei o OpenCSV no passado.

import au.com.bytecode.opencsv.CSVReader;

String fileName = "data.csv";
Leitor de CSVReader = novo CSVReader (novo FileReader (fileName));

// se a primeira linha é o cabeçalho String [] header = reader.readNext ();
// itera sobre reader.readNext até retornar nulo String [] line = reader.readNext ();

Havia outras opções nas respostas a outra pergunta .

Jay R.
fonte
Infelizmente, o download mais recente do OpenCSV (v2.2 no momento do comentário) não é compilado e não fornece um binário pré-criado.
opyate 21/03
9
O pacote que baixei do SourceForge tinha um binário na pasta deploy.
precisa
8
Se você estiver usando o maven, observe que o código de dependência no site oficial contém a declaração de versão "2.0", que possui alguns bugs, mas há a versão 2.3 atualizada nos repositórios.
broundee
essa lib não escreve arquivo em thread separado, não?
Ewoks
3
de acordo com github.com/uniVocity/csv-parsers-comparison em média 73% mais lento que o uniVocity ..
Ewoks
32

Atualização: o código nesta resposta é para Super CSV 1.52. Exemplos de código atualizados para o Super CSV 2.4.0 podem ser encontrados no site do projeto: http://super-csv.github.io/super-csv/index.html


O projeto SuperCSV suporta diretamente a análise e manipulação estruturada de células CSV. Em http://super-csv.github.io/super-csv/examples_reading.html, você encontrará, por exemplo

dada uma aula

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 que você tem um arquivo CSV com um cabeçalho. Vamos assumir o seguinte conteúdo

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

Você pode criar uma instância do UserBean e preenchê-la com valores da segunda linha do arquivo com o seguinte código

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();
    }
  }
}

usando a seguinte "especificação de manipulação"

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
};
kbg
fonte
1
Seu código não seria compilado, então enviei algumas correções. Além disso, ParseDate () não funciona corretamente, então substituí-o para ler uma String. Pode ser analisado mais tarde.
1
Limitação Big: SuperCSV não é threadsafe, eu vou olhar para Jackson, embora possa ser mais recurso limitado
ZiglioUK
O SuperCsv também não permite o uso de multimaps. Seria bom vê-lo funcionar com o MultiMaps.
Sid
19

A leitura da descrição do formato CSV me faz sentir que usar a biblioteca de terceiros seria menos dor de cabeça do que escrevê-la:

A Wikipedia lista 10 ou algo conhecido bibliotecas:

Eu comparei as bibliotecas listadas usando algum tipo de lista de verificação. O OpenCSV acabou sendo um vencedor para mim (YMMV) com os seguintes resultados:

+ 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)
mosquito
fonte
8

Usamos JavaCSV , funciona muito bem

Mat Mannion
fonte
3
O único problema desta biblioteca é que ela não permitirá a saída de arquivos CSV com terminadores de linha do Windows ( \r\n) quando não estiver em execução no Windows. O autor não fornece suporte há anos. Eu tive que desembolsar-lo para permitir que característica ausente: JavaCSV 2.2
Mosty Mostacho
6

Para o último aplicativo corporativo em que trabalhei, era necessário lidar com uma quantidade notável de CSV - há alguns meses - usei o SuperCSV no sourceforge e achei simples, robusto e sem problemas.

Cheekysoft
fonte
+1 para SuperCSV, mas possui alguns erros desagradáveis ​​que ainda não foram corrigidos, novos erros não são tratados atualmente e o último lançamento tem quase dois anos. Mas estamos usando uma versão corrigida / modificada na produção sem problemas.
21710
2
O @MRalwasser Super CSV 2.0.0-beta-1 foi lançado recentemente. Ele inclui muitas correções de bugs e novos recursos (incluindo suporte Maven e uma nova extensão Dozer para mapear propriedades e matrizes aninhadas / Coleções)
James Bassett
1
@ Hound-Dog Obrigado pela atualização, eu já notei a nova versão beta e estou feliz por ver o projeto vivo - embora a frequência de confirmações ainda me tema um pouco (quase todas confirmam apenas em alguns dias). Mas vou dar uma olhada. Existe uma data estimada de lançamento do 2.0 final?
213121 MRalwasser
2
@MRalwasser Eu sou o único desenvolvedor no momento e tenho trabalho em período integral, por isso costumo trabalhar nisso sempre que recebo um fim de semana gratuito - daí o esporádico se comprometer :) Quase 1000 downloads SF da versão beta agora e sem bugs, então estamos procurando um lançamento final no início do próximo mês. Se você tiver alguma idéia para recursos futuros, informe-nos.
James Bassett
1
SuperCSV não é threadsafe nesta fase, que faz imho não muito robusto
ZiglioUK
5

Você pode usar a csvreader api e fazer o download no seguinte local:

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

ou

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

Use o seguinte código:

/ ************ 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();
        }

    }

}

Gravar / Anexar ao arquivo CSV

Código:

/************* 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();
        }

    }
}
Dhananjay Joshi
fonte
3

Há também o utilitário CSV / Excel . Ele assume que todos esses dados são semelhantes a tabelas e fornece dados de Iteradores.

Frank
fonte
2

O formato CSV parece fácil o suficiente para o StringTokenizer, mas pode se tornar mais complicado. Aqui na Alemanha, um ponto e vírgula é usado como delimitador e as células que contêm delimitadores precisam ser escapadas. Você não vai lidar com isso facilmente com o StringTokenizer.

Eu iria para http://sourceforge.net/projects/javacsv

Paulo
fonte
0

Se você pretende ler csv no excel, existem alguns casos interessantes. Não me lembro de todos, mas o apache commons csv não foi capaz de manipulá-lo corretamente (com, por exemplo, URLs).

Teste a saída do Excel com aspas e vírgulas e barras por todo o lugar.

daveb
fonte
A biblioteca CSV do Apache Commons oferece uma variante específica para o Microsoft Excel . Não sei se isso agora lida com os problemas que você mencionou ou não.
Basil Bourque