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

Однозначные парсеры

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

1. Введение

В этом руководстве мы кратко рассмотрим Univocity Parsers , библиотеку для анализа файлов CSV, TSV и файлов с фиксированной шириной в Java.

Мы начнем с основ чтения и записи файлов, а затем перейдем к чтению и записи файлов в Java-бины и из них. Затем мы кратко рассмотрим параметры конфигурации, прежде чем завершить.

2. Настройка

Чтобы использовать синтаксические анализаторы, нам нужно добавить последнюю зависимость Maven в файл нашего проекта pom.xml :

<dependency>
<groupId>com.univocity</groupId>
<artifactId>univocity-parsers</artifactId>
<version>2.8.4</version>
</dependency>

3. Основное использование

3.1. Чтение

В Univocity мы можем быстро разобрать весь файл на набор массивов String , представляющих каждую строку в файле.

Во-первых, давайте проанализируем CSV-файл, предоставив Reader для нашего CSV-файла в CsvParser с настройками по умолчанию:

try (Reader inputReader = new InputStreamReader(new FileInputStream(
new File("src/test/resources/productList.csv")), "UTF-8")) {
CsvParser parser = new CsvParser(new CsvParserSettings());
List<String[]> parsedRows = parser.parseAll(inputReader);
return parsedRows;
} catch (IOException e) {
// handle exception
}

Мы можем легко переключить эту логику на анализ файла TSV, переключившись на TsvParser и предоставив ему файл TSV.

Обработка файла фиксированной ширины лишь немного сложнее. Основное отличие состоит в том, что нам нужно указать ширину полей в настройках парсера.

Давайте прочитаем файл с фиксированной шириной, предоставив объект FixedWidthFields нашему FixedWidthParserSettings :

try (Reader inputReader = new InputStreamReader(new FileInputStream(
new File("src/test/resources/productList.txt")), "UTF-8")) {
FixedWidthFields fieldLengths = new FixedWidthFields(8, 30, 10);
FixedWidthParserSettings settings = new FixedWidthParserSettings(fieldLengths);

FixedWidthParser parser = new FixedWidthParser(settings);
List<String[]> parsedRows = parser.parseAll(inputReader);
return parsedRows;
} catch (IOException e) {
// handle exception
}

3.2. Пишу

Теперь, когда мы рассмотрели чтение файлов парсерами, давайте научимся их записывать.

Запись файлов очень похожа на их чтение, поскольку мы предоставляем Writer вместе с желаемыми настройками анализатору, который соответствует нашему типу файла.

Давайте создадим метод для записи файлов во всех трех возможных форматах:

public boolean writeData(List<Object[]> products, OutputType outputType, String outputPath) {
try (Writer outputWriter = new OutputStreamWriter(new FileOutputStream(new File(outputPath)),"UTF-8")){
switch(outputType) {
case CSV:
CsvWriter writer = new CsvWriter(outputWriter, new CsvWriterSettings());
writer.writeRowsAndClose(products);
break;
case TSV:
TsvWriter writer = new TsvWriter(outputWriter, new TsvWriterSettings());
writer.writeRowsAndClose(products);
break;
case FIXED_WIDTH:
FixedWidthFields fieldLengths = new FixedWidthFields(8, 30, 10);
FixedWidthWriterSettings settings = new FixedWidthWriterSettings(fieldLengths);
FixedWidthWriter writer = new FixedWidthWriter(outputWriter, settings);
writer.writeRowsAndClose(products);
break;
default:
logger.warn("Invalid OutputType: " + outputType);
return false;
}
return true;
} catch (IOException e) {
// handle exception
}
}

Как и при чтении файлов, запись файлов CSV и TSV практически идентична. Для файлов с фиксированной шириной мы должны указать ширину поля в наших настройках.

3.3. Использование процессоров строк

Univocity предоставляет несколько обработчиков строк, которые мы можем использовать, а также дает нам возможность создавать свои собственные.

Чтобы получить представление об использовании обработчиков строк, давайте воспользуемся BatchedColumnProcessor для обработки большого CSV-файла пакетами из пяти строк:

try (Reader inputReader = new InputStreamReader(new FileInputStream(new File(relativePath)), "UTF-8")) {
CsvParserSettings settings = new CsvParserSettings();
settings.setProcessor(new BatchedColumnProcessor(5) {
@Override
public void batchProcessed(int rowsInThisBatch) {}
});
CsvParser parser = new CsvParser(settings);
List<String[]> parsedRows = parser.parseAll(inputReader);
return parsedRows;
} catch (IOException e) {
// handle exception
}

Чтобы использовать этот обработчик строк, мы определяем его в наших CsvParserSettings, а затем все, что нам нужно сделать, это вызвать parseAll .

3.4. Чтение и запись в Java Beans

Со списком массивов String все в порядке, но мы часто работаем с данными в Java-бинах. Univocity также позволяет читать и записывать в специально аннотированные Java-бины.

Давайте определим bean-компонент Product с аннотациями Univocity:

public class Product {

@Parsed(field = "product_no")
private String productNumber;

@Parsed
private String description;

@Parsed(field = "unit_price")
private float unitPrice;

// getters and setters
}

Основной аннотацией является аннотация @Parsed .

Если заголовок нашего столбца совпадает с именем поля, мы можем использовать @Parsed без указания каких-либо значений. Если заголовок нашего столбца отличается от имени поля, мы можем указать заголовок столбца, используя свойство поля .

Теперь, когда мы определили наш bean-компонент Product , давайте прочитаем в него наш CSV-файл:

try (Reader inputReader = new InputStreamReader(new FileInputStream(
new File("src/test/resources/productList.csv")), "UTF-8")) {
BeanListProcessor<Product> rowProcessor = new BeanListProcessor<Product>(Product.class);
CsvParserSettings settings = new CsvParserSettings();
settings.setHeaderExtractionEnabled(true);
settings.setProcessor(rowProcessor);
CsvParser parser = new CsvParser(settings);
parser.parse(inputReader);
return rowProcessor.getBeans();
} catch (IOException e) {
// handle exception
}

Сначала мы создали специальный процессор строк BeanListProcessor с нашим аннотированным классом. Затем мы предоставили это CsvParserSettings и использовали для чтения списка Product s.

Далее, давайте запишем наш список Product в файл фиксированной ширины:

try (Writer outputWriter = new OutputStreamWriter(new FileOutputStream(new File(outputPath)), "UTF-8")) {
BeanWriterProcessor<Product> rowProcessor = new BeanWriterProcessor<Product>(Product.class);
FixedWidthFields fieldLengths = new FixedWidthFields(8, 30, 10);
FixedWidthWriterSettings settings = new FixedWidthWriterSettings(fieldLengths);
settings.setHeaders("product_no", "description", "unit_price");
settings.setRowWriterProcessor(rowProcessor);
FixedWidthWriter writer = new FixedWidthWriter(outputWriter, settings);
writer.writeHeaders();
for (Product product : products) {
writer.processRecord(product);
}
writer.close();
return true;
} catch (IOException e) {
// handle exception
}

Заметное отличие состоит в том, что мы указываем заголовки наших столбцов в наших настройках.

4. Настройки

В Univocity есть ряд настроек, которые мы можем применить к парсерам. Как мы видели ранее, мы можем использовать настройки для применения обработчика строк к синтаксическим анализаторам.

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

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

CsvParserSettings settings = new CsvParserSettings();
settings.setMaxCharsPerColumn(100);
settings.setMaxColumns(50);
CsvParser parser = new CsvParser(new CsvParserSettings());

5. Вывод

В этом кратком руководстве мы изучили основы парсинга файлов с помощью библиотеки Univocity.

Мы научились читать и записывать файлы как в списки строковых массивов, так и в Java-бины. Перед тем, как перейти к Java bean-компонентам, мы кратко рассмотрели использование различных обработчиков строк. Наконец, мы кратко коснулись того, как настроить параметры.

Как всегда, исходный код доступен на GitHub .