Настроить CSVFormat.RFC4180 - PullRequest
0 голосов
/ 07 мая 2018

Я должен прочитать CSV-файл. Файл может содержать любой разделитель и может быть заключен в "" \ "или нет. Файл также должен быть проанализирован относительно RFC4180. (Я знаю, что в RFC4180 разделитель - это", ", но пользователь также должен иметь возможность читать например, файл, разделенный знаком «|»).

public List<List<String>> readFileAsListOfList(File file, String delimiter, String lineEnding, String enclosure) throws Exception {
        if (!file.exists()) {
            throw new Exception("File doesn't exist.");
        }
        if (!file.isFile()) {
            throw new Exception("File must be a file.");
        }

        List<List<String>> fileContent = new ArrayList<>();
        CSVFormat csvFormat = CSVFormat.RFC4180.withDelimiter(delimiter.charAt(0)).withEscape(lineEnding.charAt(0));
        if (StringUtils.isNotEmpty(enclosure)) {
            csvFormat.withQuote(enclosure.charAt(0));
        } else {
            csvFormat.withQuote(null);
        }
        System.out.println(csvFormat);
        List<String> lineContent = new ArrayList<>();
        for (CSVRecord rec : csvFormat.parse(new FileReader(file))) {
            for (String field : rec) {
                lineContent.add(field);
            }
            fileContent.add(lineContent);
        }
        return fileContent;
    }

Если у меня сейчас дело, что файл не заключен, и у меня есть строка вроде

ааа | ГЭБ | "| ссс

Я получаю следующую ошибку:

Исключение в потоке "main" java.lang.IllegalStateException: IOException читает следующую запись: java.io.IOException: (startline 120707) Достигнут EOF до завершения инкапсулированного токена org.apache.commons.csv.CSVParser $ 1.getNextRecord (CSVParser.java:530) в org.apache.commons.csv.CSVParser $ 1.hasNext (CSVParser.java:540) в com.ids.dam.pim.validation.CSVFileReaderApache.readFileAsListOfList (CSVFileReaderApache.java:61) в com.ids.dam.pim.validation.CSVFileReaderApache.main (CSVFileReaderApache.java:78) Вызвано: java.io.IOException: (стартовая строка 120707) EOF достигнут раньше заключенный в капсулу токен org.apache.commons.csv.Lexer.parseEncapsulatedToken (Lexer.java:288) в org.apache.commons.csv.Lexer.nextToken (Lexer.java:158) в org.apache.commons.csv.CSVParser.nextRecord (CSVParser.java:586) в org.apache.commons.csv.CSVParser $ 1.getNextRecord (CSVParser.java:527) ... еще 3

Я думаю, это потому, что мой CSVFormat все еще содержит двойную кавычку в качестве приложения, потому что это по умолчанию в RFC4180.

Распечатка в формате дает следующее:

Delimiter=<|> Escape=<L> QuoteChar=<"> RecordSeparator=<
> SkipHeaderRecord:false

Для меня это означает, что я могу перезаписать разделитель по умолчанию с помощью CSVFormat.RFC4180.withDelimiter(delimiter.charAt(0)..., но я не могу установить вложение равным нулю

Есть ли способ установить нулевое значение для корпуса, все еще используя RFC4180?

1 Ответ

0 голосов
/ 07 мая 2018

Цитирование всегда обязательно в CSV, и символ цитирования может быть выбран как разделитель. Если вы знаете, что в вашем файле используется разделитель |, а кавычек нет, вам следует создать CSVFormat таким образом. И будьте осторожны, withOption(...) не применяет параметр к текущему формату csv, но возвращает теперь тот же, что и оригинал, но с установленным параметром. Из Apache CSVFormat javadoc

public CSVFormat withQuoteMode(QuoteMode quoteModePolicy)

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

Возвращает: Новый CSVFormat , равный этому, но с указанной политикой котировок

Вы должны использовать:

    CSVFormat csvFormat = CSVFormat.RFC4180.withDelimiter(delimiter.charAt(0))
            .withEscape(lineEnding.charAt(0));
    if (StringUtils.isNotEmpty(enclosure)) {
        csvFormat = csvFormat.withQuote(enclosure.charAt(0));
    } else {
        csvFormat = csvFormat.withQuoteMode(NONE);
    }
...