Использование Java opencsv 4.5 - Советы - PullRequest
0 голосов
/ 28 февраля 2019

Недавно мне нужно было читать и писать CSV-файл с использованием bean-компонентов.В процессе и после изучения сотен постов я разработал функциональное решение.Этот пост - больше советов и хитростей, чем вопроса ... надеюсь, он сократит ваши усилия и позволит избежать поразительной странности ошибок, которые вы получите, если не будете следовать этим советам ...

1), чтобыиспользовать opencsv с CsvToBean, вам нужно включить ВСЕ эти файлы JAR в ваш проект (я добавил их в мой путь сборки как 'External JAR' в eclipse):

commons-beanutils-1.9.3.jar
commons-collections-3.2.jar
commons-collections4-4.3.jar
commons-lang3-3.8.1.jar
opencsv-4.5.jar

Да - вам нужны обе версииколлекции commons для чтения и записи bean-компонентов.

2) При создании вашего класса bean-компонентов свойства и методы set / get ДОЛЖНЫ иметь определенный синтаксис, в противном случае чтение / запись не удастся (opencsv использует самоанализ и отражениево время выполнения).В основном, ваши свойства должны быть в нижнем регистре:

Private String ppppp; …

, а процедуры get / set должны использовать только первую букву свойства:

public String getPpppp() …
public void setPpppp(String  value) …

3) Использовать @CsvBindByName или@CsvBindByPosition При привязке по имени будет задано имя столбца, который будет сопоставлен со свойством при чтении, при привязке по позиции будет установлен порядок вывода при записи.(bindbyposition также установит позицию поля для чтения, если в вашем csv-файле нет заголовков).

@CsvBindByName(column = "ID", required = true)
@CsvBindByPosition(position = 0)
Private String pppppp;

Не включайте «required = true», если какие-либо данные в этом столбце будут нулевыми илипусто.

4) Ваш класс бина должен иметь нулевой конструктор: (Если имя класса «Account») *

public Account() {
}

Пример файла класса

---------------- Account.java -------------------

package MyCsv;

import java.util.Optional;
import com.opencsv.*;
import com.opencsv.bean.*;

public class Account {

    @CsvBindByName(column = "PERSONNEL_ID", required = true)
    @CsvBindByPosition(position = 0)
    private String personnelid;

    @CsvBindByName(column = "LAST_NAME")
    @CsvBindByPosition(position = 1)
    private String lastname;

// set as constructor
    public Account() {
    }

    public String getPersonnelid()
    {
        return this.personnelid;
    }

    public void setPersonnelid(String value)
    {
        this.personnelid = value;
    }
    public String getLastname()
    {
        return this.lastname;
    }

    public void setLastname(String value)
    {
        this.lastname = value;
    }
    @Override
    public String toString() {
        return "Account [personnelid=" + this.personnelid + ", 
                     “ lastname=" + this.lastname);
    }
}

---------------- end Account.java -------------------

5) Используйте [stateful] CsvToBeanBuilder для настройкиВаш CSV Reader.

…
    List<Account> Accounts = null;
…
    try {
        Reader freader = new FileReader(inFileName); 
        HeaderColumnNameMappingStrategy<Account> beanStrategy = new HeaderColumnNameMappingStrategy<Account>();
        beanStrategy.setType(Account.class);
        CsvToBean<Account> csvToBean = new CsvToBeanBuilder<Account>(freader)
                .withType(Account.class)
                .withIgnoreLeadingWhiteSpace(true)
                .withMappingStrategy(beanStrategy)
                .build();
        // reads all “Account”s – entire file - into a list of Account beans
        Accounts = csvToBean.parse();
        freader.close();
    }
    catch (Exception e)
    {
        e.printStackTrace();
    }

6) Используйте StatefulBeanToCsvBuilder для настройки вашего устройства записи.(Вы можете использовать один и тот же класс для чтения и записи, если вы не меняете порядок поля чтения при записи):

Writer writer = new FileWriter(outFileName);

StatefulBeanToCsvBuilder<Account> builder = new StatefulBeanToCsvBuilder<Account>(writer);
StatefulBeanToCsv<Account> beanWriter = builder.build();

// build a header for output & make it the first record in your list
// requires a parameterized constructor (not shown above for brevity)
Account accountHeader = new Account("PersonnelID","LastName");
Accounts.add(0, accountHeader);

try {
    // writes all of the account beans in the accounts list at once
    beanWriter.write(Accounts);
} catch (CsvDataTypeMismatchException e) {
    e.printStackTrace();
} catch (CsvRequiredFieldEmptyException e) {
    e.printStackTrace();
}

writer.flush();
writer.close();

7) Не забудьте очистить и закрыть файл «записи» и закрытьВаш прочитанный файл…

8) Сделайте все поля ваших строк.Если вам нужно сделать целое число или дату, делайте это явно в коде, когда вам это нужно.У меня были непредсказуемые результаты, когда у класса компонента были свойства, объявленные с помощью int или LocalDate.Самый простой способ сделать это - добавить get'ers и set'ers, которые обрабатывают преобразования в вашем классе бинов:

Public LocalDate getAsDatePpppp() …

Public void setAsDatePpppp(LocalDate theDateToSet) ...
...