CSV API для Java [закрито]


164

Хто-небудь може порекомендувати простий API, який дозволить мені використовувати читання вхідного файлу CSV, зробити кілька простих перетворень, а потім записати його.

Швидкий Google знайшов http://flatpack.sourceforge.net/, який виглядає багатообіцяючим.

Я просто хотів перевірити, що використовують інші, перш ніж приєднатися до цього API.


Використовуйте дочірній сайт Програмне забезпечення Рекомендації Stack Exchange, коли запитуєте пропозиції щодо бібліотеки програмного забезпечення. Має кілька звернень до Java & CSV .
Василь Бурк

Відповіді:


32

Apache Commons CSV

Перевірте загальний CSV Apache .

Ця бібліотека читає і записує кілька варіантів CSV , включаючи стандартний RFC 4180 . Також читає / записує файли з обмеженими вкладками .

  • Excel
  • InformixUnload
  • InformixUnloadCsv
  • MySQL
  • Oracle
  • PostgreSQLCsv
  • PostgreSQLText
  • RFC4180
  • TDF

Я використовував CSV з пісочним кодом досить довгий час і жодного разу не відчував проблем. Я дуже сподіваюсь, що вони сприятимуть його повноцінній роботі та вийдуть із пісочниці.
Алекс Маршалл

3
@ Bmatthews68 посилання пісочниця неіснуючої - виглядає він переїхав в Apache Commons власне (я редагував посилання у відповідь теж)
drevicko

Приклади Apache Commons тут: apisonar.com/java-examples/org.apache.commons.csv.html
APISonar

83

Раніше я використовував OpenCSV .

import au.com.bytecode.opencsv.CSVReader;

String fileName = "data.csv";
CSVReader Reader = новий CSVReader (новий FileReader (fileName));

// якщо перший рядок - заголовок String [] header = reader.readNext ();
// ітерація читача.readNext, поки вона не повернеться в нуль String [] рядок = читач.readNext ();

У відповідях на інше запитання були й інші варіанти .


На жаль, остання завантаженість OpenCSV (v2.2 під час коментування) не збирається, і вони не надають попередньо вбудований бінарний файл.
опіят

9
Пакет, який я завантажив з SourceForge, мав двійковий файл у папці розгортання.
Майк Сіклер

8
Якщо ви використовуєте maven, зауважте, що код залежності на офіційному веб-сайті містить декларацію версії "2.0", яка містить деякі помилки, але в репозиторіях є оновлена ​​версія 2.3.
broundee

ця lib не записує файл в окрему нитку, ні?
Ewoks

3
Згідно з даними github.com/uniVocity/csv-parsers-comparing в середньому на 73% повільніше, ніж uniVocity ..
Ewoks

32

Оновлення: Код у цій відповіді призначений для Super CSV 1.52. Оновлені приклади коду для Super CSV 2.4.0 можна знайти на веб-сайті проекту: http://super-csv.github.io/super-csv/index.html


Проект SuperCSV безпосередньо підтримує розбір та структуровану маніпуляцію осередками CSV. З http://super-csv.github.io/super-csv/examples_reading.html ви знайдете, наприклад,

дали клас

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

і у вас є файл CSV із заголовком. Припустимо наступний зміст

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

Потім ви можете створити екземпляр UserBean і заповнити його значеннями з другого рядка файла із наступним кодом

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

використовуючи наступну "специфікацію маніпуляції"

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
Ваш код не збирається, тому я внесла деякі виправлення. Також ParseDate () не працює належним чином, тому я замінив його на читання String. Його можна розібрати пізніше.

1
Велике обмеження: SuperCSV не є безпечним для потоків, я шукаю Джексона, хоча це може бути більш обмеженою функцією
ZiglioUK

SuperCsv також не дозволяє використовувати мультимапи. Було б добре бачити, як це працює з MultiMaps.
Сід

19

Читаючи опис формату CSV, я відчуваю, що використання бібліотеки сторонніх організацій буде менше головного болю, ніж її написання:

У Вікіпедії перелічено 10 або щось відоме бібліотеки:

Я порівнював перелічені лісти, використовуючи якийсь контрольний список. OpenCSV виявив мене переможцем (YMMV) з такими результатами:

+ 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

Ми використовуємо JavaCSV , він працює досить добре


3
Єдина проблема з цією бібліотекою полягає в тому, що вона не дозволить вам виводити файли CSV за допомогою лінійних термінаторів Windows ( \r\n), коли вони не працюють у Windows. Автор не надав підтримку роками. Мені довелося розщедритися, щоб дозволити цю відсутність функції: JavaCSV 2.2
Mosty Mostacho

6

Для останнього корпоративного додатку я працював над тим, що потрібно було обробляти значну кількість CSV - пару місяців тому - я використовував SuperCSV у sourceforge і вважав його простим, надійним та безпроблемним.


+1 для SuperCSV, але в ньому є деякі неприємні помилки, які ще не виправлені, нові помилки наразі не обробляються, а останньому випуску - майже два роки. Але ми використовуємо виправлену / модифіковану версію у виробництві без проблем.
MRalwasser

2
Нещодавно вийшов @MRalwasser Super CSV 2.0.0-beta-1 . Вона включає багато виправлень помилок та нових функцій (включаючи підтримку Maven та нове розширення Dozer для відображення вкладених властивостей та масивів / колекцій)
James Bassett

1
@ Hound-Dog Дякую за оновлення, я вже помітив нову бета-версію, і я радий бачити проект живим - хоча частота комітетів все ще мене трохи побоюється (майже всі здійснюються лише за кілька днів). Але я погляну. Чи є приблизна дата випуску остаточного 2.0?
MRalwasser

2
@MRalwasser Я єдиний розробник на даний момент і маю повний робочий день, тому я прагну працювати над цим щоразу, коли отримую вільний вихідний - отже, спорадичні зобов’язання :) Близько 1000 завантажень бета-версії бета-версії зараз, і помилок немає, тому шукаємо на шляху до остаточного випуску на початку наступного місяця. Якщо у вас є якісь ідеї щодо майбутніх функцій, повідомте нас про це.
Джеймс Бассетт

1
На цьому етапі SuperCSV не є безпечним для потоків, що робить його не дуже надійним
ZiglioUK

5

Ви можете використовувати csvreader api та завантажити з наступного місця:

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

або

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

Використовуйте наступний код:

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

    }

}

Написати / додати до файлу CSV

Код:

/************* 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

Формат CSV звучить досить просто для StringTokenizer, але він може ускладнитися. Тут, у Німеччині, крапкою з комою використовується розмежувач, а комірки, що містять роздільники, потрібно уникнути. Ви не збираєтеся легко впоратися зі StringTokenizer.

Я б пішов на http://sourceforge.net/projects/javacsv


0

Якщо ви маєте намір прочитати CSV з excel, то є кілька цікавих кутових випадків. Я не можу їх усіх запам’ятати, але апарат apache commons csv був не в змозі правильно поводитися з ним (наприклад, з URL-адресами).

Не забудьте протестувати результат вищого рівня з цитатами, комами та косою рисою.


Apache Commons CSV бібліотека дійсно пропонує варіант специфічний для Microsoft Excel . Я не знаю, чи вирішує це зараз проблеми, які ви згадуєте, чи ні.
Василь Бурк
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.