Перейти к основному содержимому

Введение в OpenCSV

· 6 мин. чтения

Задача: Сумма двух чисел

Напишите функцию twoSum. Которая получает массив целых чисел nums и целую сумму target, а возвращает индексы двух чисел, сумма которых равна target. Любой набор входных данных имеет ровно одно решение, и вы не можете использовать один и тот же элемент дважды. Ответ можно возвращать в любом порядке...

ANDROMEDA

1. Введение

В этом кратком руководстве мы познакомимся с OpenCSV 4, фантастической библиотекой для записи, чтения, сериализации, десериализации и/или анализа файлов .csv . Затем мы рассмотрим несколько примеров, демонстрирующих, как настроить и использовать OpenCSV 4 для наших целей.

2. Настройка

Во-первых, мы добавим OpenCSV в наш проект с помощью зависимости pom.xml :

<dependency>
<groupId>com.opencsv</groupId>
<artifactId>opencsv</artifactId>
<version>4.1</version>
</dependency>

.jars для OpenCSV можно найти на официальном сайте или с помощью быстрого поиска в репозитории Maven .

Наш файл .csv будет очень простым; мы сохраним его до двух столбцов и четырех строк:

colA, ColB
A, B
C, D
G, G
G, F

3. Быть или не быть фасолью

После добавления OpenCSV в наш pom.xml мы можем реализовать методы обработки CSV двумя удобными способами:

  1. используя удобные объекты CSVReader и CSVWriter (для более простых операций)
  2. использование CsvToBean для преобразования файлов .csv в bean-компоненты (которые реализованы как аннотированные обычные-старые-java-объекты )

В этой статье мы остановимся на синхронных (или блокирующих ) примерах, чтобы сосредоточиться на основах.

Помните, что синхронный метод предотвратит выполнение окружающего или последующего кода до тех пор, пока он не будет выполнен. В рабочих средах, скорее всего, будут использоваться асинхронные (или неблокирующие ) методы, которые позволят другим процессам или методам завершиться, пока завершается асинхронный метод.

Мы рассмотрим асинхронные примеры для OpenCSV в следующей статье.

3.1. CSVReader _ ``

Давайте изучим CSVReader с помощью предоставленных методов readAll() и readNext() . Мы рассмотрим, как использовать readAll () синхронно:

public List<String[]> readAll(Reader reader) throws Exception {
CSVReader csvReader = new CSVReader(reader);
List<String[]> list = new ArrayList<>();
list = csvReader.readAll();
reader.close();
csvReader.close();
return list;
}

Затем мы можем вызвать этот метод, передав BufferedReader :

public String readAllExample() throws Exception {
Reader reader = Files.newBufferedReader(Paths.get(
ClassLoader.getSystemResource("csv/twoColumn.csv").toURI()));
return CsvReaderExamples.readAll(reader).toString();
}

Точно так же мы можем абстрагироваться от функции readNext (), которая считывает предоставленный .csv построчно:

public List<String[]> oneByOne(Reader reader) throws Exception {
List<String[]> list = new ArrayList<>();
CSVReader csvReader = new CSVReader(reader);
String[] line;
while ((line = csvReader.readNext()) != null) {
list.add(line);
}
reader.close();
csvReader.close();
return list;
}

Наконец, мы можем вызвать этот метод здесь, передав BufferReader:

public String oneByOneExample() throws Exception {
Reader reader = Files.newBufferedReader(Paths.get(
ClassLoader.getSystemResource("csv/twoColumn.csv").toURI()));
return CsvReaderExamples.oneByOne(reader).toString();
}

В качестве альтернативы, для большей гибкости и возможностей настройки, мы можем использовать CSVReaderBuilder :

CSVParser parser = new CSVParserBuilder()
.withSeparator(',')
.withIgnoreQuotations(true)
.build();

CSVReader csvReader = new CSVReaderBuilder(reader)
.withSkipLines(0)
.withCSVParser(parser)
.build();

CSVReaderBuilder позволяет нам пропускать заголовки столбцов и задавать правила парсинга через CSVParserBuilder .

Используя CSVParserBuilder , мы можем выбрать собственный разделитель столбцов, игнорировать или обрабатывать кавычки, указать, как мы будем обрабатывать пустые поля и как мы будем интерпретировать экранированные символы. Для получения дополнительной информации об этих параметрах конфигурации обратитесь к официальной документации спецификации .

Как всегда, нам нужно не забыть закрыть все наши программы чтения , чтобы предотвратить утечку памяти.

3.2. CSVWriter _ ``

Аналогичным образом CSVWriter предоставляет возможность записи в файл .csv сразу или построчно.

Давайте посмотрим, как писать в .csv построчно:

public String csvWriterOneByOne(List<String[]> stringArray, Path path) throws Exception {
CSVWriter writer = new CSVWriter(new FileWriter(path.toString()));
for (String[] array : stringArray) {
writer.writeNext(array);
}

writer.close();
return Helpers.readFile(path);
}

Затем мы укажем, где мы хотим сохранить этот файл, и вызовем метод, который мы только что написали:

public String csvWriterSyncOneByOne() throws Exception{
Path path = Paths.get(
ClassLoader.getSystemResource("csv/writtenOneByOne.csv").toURI());
return CsvWriterExamples.csvWriterOneByOne(Helpers.fourColumnCsvString(), path);
}

Мы также можем написать наш .csv сразу, передав массивы List of String , представляющие строки нашего .csv:

public String csvWriterAll(List<String[]> stringArray, Path path) throws Exception {
CSVWriter writer = new CSVWriter(new FileWriter(path.toString()));
writer.writeAll(stringArray);
writer.close();
return Helpers.readFile(path);
}

Наконец, вот как мы это называем:

public String csvWriterSyncAll() throws Exception {
Path path = Paths.get(
ClassLoader.getSystemResource("csv/writtenAll.csv").toURI());
return CsvWriterExamples.csvWriterAll(Helpers.fourColumnCsvString(), path);
}

3.3. Чтение на основе компонентов

OpenCSV может сериализовать файлы .csv в предустановленные и повторно используемые схемы, реализованные в виде аннотированных Java-компонентов pojo . CsvToBean создается с использованием CsvToBeanBuilder . Начиная с OpenCSV 4, CsvToBeanBuilder является рекомендуемым способом работы с com.opencsv.bean.CsvToBean.

Вот простой bean-компонент, который мы можем использовать для сериализации нашего двухколоночного .csv из раздела 2. :

public class SimplePositionBean  {
@CsvBindByPosition(position = 0)
private String exampleColOne;

@CsvBindByPosition(position = 1)
private String exampleColTwo;

// getters and setters
}

Каждый столбец в файле .csv связан с полем в bean-компоненте. Мы можем выполнять сопоставления между заголовками столбцов .csv , используя аннотации @CsvBindByPosition или @CsvBindByName , которые определяют сопоставление по положению или совпадению строки заголовка соответственно.

Во-первых, мы создадим суперкласс с именем CsvBean, который позволит нам повторно использовать и обобщать методы, которые мы создадим ниже:

public class CsvBean { }

Вот пример дочернего класса:

public class NamedColumnBean extends CsvBean {

@CsvBindByName(column = "name")
private String name;

@CsvBindByName
private int age;

// getters and setters
}

Далее мы абстрагируем синхронно возвращаемый список с помощью CsvToBean :

public List<CsvBean> beanBuilderExample(Path path, Class clazz) throws Exception {
CsvTransfer csvTransfer = new CsvTransfer();
ColumnPositionMappingStrategy ms = new ColumnPositionMappingStrategy();
ms.setType(clazz);

Reader reader = Files.newBufferedReader(path);
CsvToBean cb = new CsvToBeanBuilder(reader)
.withType(clazz)
.withMappingStrategy(ms)
.build();

csvTransfer.setCsvList(cb.parse());
reader.close();
return csvTransfer.getCsvList();
}

Затем мы передаем наш компонент ( clazz ) и устанавливаем его как ColumnPositionMappingStrategy . При этом мы связываем поля наших bean-компонентов с соответствующими столбцами наших строк .csv .

Мы можем вызвать это здесь, используя подкласс SimplePositionBean CsvBean , который мы написали выше:

public String simplePositionBeanExample() throws Exception {
Path path = Paths.get(
ClassLoader.getSystemResource("csv/twoColumn.csv").toURI());
return BeanExamples.beanBuilderExample(path, SimplePositionBean.class).toString();
}

Мы также можем вызвать его здесь, используя NamedColumnBean, еще один подкласс CsvBean :

public String namedColumnBeanExample() throws Exception {
Path path = Paths.get(
ClassLoader.getSystemResource("csv/namedColumn.csv").toURI());
return BeanExamples.beanBuilderExample(path, NamedColumnBean.class).toString();
}

3.4. Написание на основе компонентов

Наконец, давайте посмотрим, как использовать класс StatefulBeanToCsv для записи в файл .csv :

public String writeCsvFromBean(Path path) throws Exception {
Writer writer = new FileWriter(path.toString());

StatefulBeanToCsv sbc = new StatefulBeanToCsvBuilder(writer)
.withSeparator(CSVWriter.DEFAULT_SEPARATOR)
.build();

List<CsvBean> list = new ArrayList<>();
list.add(new WriteExampleBean("Test1", "sfdsf", "fdfd"));
list.add(new WriteExampleBean("Test2", "ipso", "facto"));

sbc.write(list);
writer.close();
return Helpers.readFile(path);
}

Здесь мы указываем, как мы будем разграничивать наши данные, которые предоставляются в виде списка указанных объектов CsvBean .

Затем мы можем вызвать наш метод writeCsvFromBean() после передачи желаемого пути к выходному файлу:

public String writeCsvFromBeanExample() {
Path path = Paths.get(
ClassLoader.getSystemResource("csv/writtenBean.csv").toURI());
return BeanExamples.writeCsvFromBean(path);
}

4. Вывод

В этой краткой статье мы обсудили примеры синхронного кода для OpenCSV с использованием bean-компонентов, CSVReader и CSVWriter . Для получения дополнительной информации ознакомьтесь с официальной документацией здесь.

Как всегда, образцы кода доступны на GitHub .