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.


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

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


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 .


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

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)

8

Usamos JavaCSV , funciona muito bem


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.


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

    }
}


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


Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.