Вступление
Это последняя статья в короткой серии, посвященной библиотекам для чтения и записи CSV на Java , и прямое продолжение предыдущей статьи - Чтение и запись CSV на Java с помощью Apache Commons CSV .
OpenCSV
OpenCSV - один из самых простых и
легких для понимания парсеров CSV, использующий стандартные Reader
/
Writer
и предлагающий CSVReader
поверх.
Как и Apache Commons CSV, OpenCSV работает с лицензией Apache 2.0. Прежде чем загружать и решать, использовать ли парсеры OpenCSVs, вы можете просмотреть исходный код и документы Java и даже проверить их набор тестов JUnit, который включен в их репозиторий git.
OpenCSV также включен вMVNRepository , что упрощает управление зависимостями.
CSVReader
позволяет получать одну запись за раз, несколько записей в
виде списка или итератора, что делает его гибким с точки зрения удобства
использования считываемых данных. Библиотека также включает в себя
удобные функции, такие как чтение, запись в компоненты и из компонентов,
а также прямое отображение из CSV в карту Java с использованием строки
заголовка.
OpenCSV не имеет такого большого разнообразия предопределенных форматов, как Apache Commons CSV. Он полагается на два парсера:
- CSVParser - исходный синтаксический анализатор, определенный в OpenCSV. Это работает для большинства простых экземпляров синтаксического анализа, но не работает, если есть escape-символы, определенные как часть самой записи.
- RFC4180Parser - аналог
CSVFormat.RFC4180
в Apache Commons CSV. Работает с CSV-файлами, отформатированными в соответствии со спецификациями RFC 4180. Эта версия анализатора рассматривает все символы между открывающими и закрывающими кавычками как содержимое, за исключением символа двойной кавычки, который необходимо экранировать другой двойной кавычкой.
Чтение CSV с OpenCSV
Чтение CSV с помощью OpenCSV происходит быстрее, чем с Apache Commons
CSV, поскольку CSVWriter
реализован как многопоточный при
использовании CSVToBean.parse()
.
CSVReader
также реализован с использованием Java Iterable , поэтому
можно управлять ограничениями памяти и времени в зависимости от
выбранного вами метода реализации.
OpenCSV имеет два типа объектов для чтения CSV - CSVReader и его подкласс CSVReaderHeaderAware .
CSVReader
похож на своего CSVParser
Apache Commons и может
использоваться как для простых, так и для сложных сценариев
синтаксического анализа.
Чтобы перебрать каждую запись в файле CSV, где record
будет массивом
строк с разделенными запятыми значениями, разделенными на отдельные
поля:
CSVReader csvReader = new CSVReader (new InputStreamReader(csvFile.getInputStream()));
while ((record = csvReader.readNext()) != null) {
// do something
}
Если ваш CSV разделен символом, отличным от запятой, вы можете вместо
этого использовать конструктор с двумя параметрами и указать
разделитель, который вы хотите использовать в CSVReader
.
Например, если ваш CSV содержит значения, разделенные табуляцией, вы
можете инициализировать CSVReader
следующим образом:
CSVReader csvReader = new CSVReader(new InputStreamReader(csvFile.getInputStream()), '\t');
OpenCSV также имеет более сложный способ синтаксического анализа файлов CSV, который включает в себя реализацию bean-компонентов для сопоставления полей в CSV, а затем использование аннотаций для определения типов записей с помощью аннотаций на основе заголовков или позиций.
Это помогает, поскольку позволяет обрабатывать записи CSV как общий набор данных, а не как набор отдельных полей.
Если имена заголовков обрабатываемого файла согласованы, вы можете
аннотировать столбцы с @CSVBindByName
аннотации @CSVBindByName и
позволить OpenCSV позаботиться о сопоставлении и копировании стороны
обработки проанализированных данных.
Например, с нашим древовидным набором данных:
public class Trees {
@CSVBindByName
private int index;
@CSVBindByName
private int girth;
@CSVBindByName
private int height;
@CSVBindByName
private int volume;
public int getIndex() {
return this.index;
}
public void setIndex(int newIndex) {
this.index = newIndex;
}
...
}
Пока ваш файл CSV содержит заголовок, названный с именами переменных в нашем объявлении класса, OpenCSV может анализировать и считывать данные в соответствующий элемент с автоматическим преобразованием типов:
List<Trees> treeParser = new CSVToBeanBuilder(FileReader("somefile.csv")).withType(Trees.class).build().parse();
При необходимости к методам получения и установки могут быть добавлены
проверки, а обязательные поля могут быть указаны путем установки
required
в аннотации.
Если имя заголовка немного отличается от имени переменной, String также можно указать в аннотации. Возможность сопоставить имя заголовка, когда имя столбца отличается, полезна в нашем примере, поскольку наш фактический набор данных содержит единицу измерения поля, а также пробелы и знаки пунктуации, которые не допускаются в стандартных именах переменных Java.
В этом случае флаг и отображение могут быть указаны с аннотацией:
...
@CSVBindByName (column = "Girth (in)", required = true)
private int girth;
...
Если ваш CSV-файл не имеет заголовка, вы можете сопоставить его по
положению столбца вместе с аннотацией @CSVBindByPosition
Имейте в виду, что позиции OpenCSV отсчитываются от 0:
public class Trees{
@CSVBindByPosition(position = 0, required = true)
private int index;
@CSVBindByPosition(position = 1, required = true)
private int girth;
@CSVBindByPosition(position = 2)
private int height;
@CSVBindByPosition(position = 3)
private int volume;
}
Если вы хотите обрабатывать более сложные сценарии, вы можете реализовать класс с интерфейсом MappingStrategy и определить схему преобразования или сопоставления, которая соответствует вашему сценарию синтаксического анализа.
Написание CSV с OpenCSV
OpenCSV имеет больше возможностей, чем Apache Commons CSV, когда дело доходит до записи данных в файлы CSV. Это позволяет вам либо писать из массива строк, либо писать из списка объектов.
Запись из списка объектов требует, чтобы объекты были инициализированы и объявлены заранее. Итак, чтобы не усложнять задачу, давайте рассмотрим работу с массивом строк.
Чтобы создать файл CSV с данными из массива строк:
CSVWriter csvWriter = new CSVWriter(new FileWriter("new.csv"), ',');
String[] records = "Index.Girth.Height.Volume".split(".");
csvWriter.writeNext(records);
csvWriter.close();
OpenCSV работает с концепцией, что CSV - это не просто значения,
разделенные запятыми; он позволяет вам определить, какой разделитель вы
хотите использовать в файле в качестве параметра в конструкторе
CSVWriter
Точно так же при определении массива String вам может быть полезно объявить String, а затем разделить его на значения на основе разделителя. Это особенно полезно, когда вам нужно скопировать выбранное подмножество строк данных из одного CSV-файла или файла базы данных в другой.
При инициализации CSVWriter
использование FileWriter
или Writer
является обязательным. Инициализация модуля записи с использованием
только одного параметра приводит к созданию файла по умолчанию,
разделенного запятыми.
Есть несколько дополнительных параметров для конкретных случаев использования:
Char separator
- разделитель. Если не объявлено, разделителем по умолчанию будет запятая.Char quotechar
- символ кавычки. Это будет использоваться в том случае, если ваш набор данных содержит значение с запятой как часть набора данных, и вам нужно сгенерировать файл, разделенный запятыми. Обычно в качестве символов кавычек используются двойные кавычки, одинарные кавычки или косые черты.Char escapechar
- обычно используется для выхода изquotechar
.String lineend
- строка или символ, определяющий конец строки данных.
Вы можете CSVWriter
включая все необязательные параметры:
CSVWriter csvWriter = new CSVWriter(new FileWriter("new.csv"), ",", "'","/", "\n");
CSVWriter
также имеет несколько полей, которые вы можете передать
конструктору в качестве параметров. Вы можете определить эти значения
как константы и повторно использовать символы и строки в кодовой базе
для сохранения согласованности.
Например, после объявления:
CSVWriter.DEFAULT_SEPARATOR = ",";
CSVWriter.DEFAULT_QUOTE_CHARACTER = "'";
CSVWriter.DEFAULT_ESCAPE_CHARACTER = "/";
CSVWriter.DEFAULT_LINE_END = "\n";
Вы можете использовать:
CSVWriter csvWriter = new CSVWriter(new FileWriter("new.csv"), CSVWriter.DEFAULT_SEPARATOR, CSVWriter.DEFAULT_QUOTE_CHARACTER, CSVWriter.DEFAULT_ESCAPE_CHARACTER, CSVWriter.DEFAULT_LINE_END);
Или используйте OpenCSV, используя значения по умолчанию, если значения не определены явно в конструкторе, и просто вызовите:
CSVWriter csvWriter = new CSVWriter(new FileWriter("new.csv"));
Поэтому, если ваши данные включают строку с именем пользователя и адресом, например: JohnDoe, 19/2, ABC Street, Someplace , фактический формат строки, в котором вам нужно, чтобы это было "JohnDoe", "19 // Улица ABC, 2 /, Где-то " .
Заключение
OpenCSV - один из самых простых и
легких для понимания парсеров CSV, использующий стандартные Reader
/
Writer
и предлагающий CSVReader
поверх.