0

我必须阅读一个 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;
    }

如果我现在有文件未包含的情况,并且我有一行

aaa|bbb|"|ccc

我收到以下错误:

线程“main”中的异常 java.lang.IllegalStateException:IOException 读取下一条记录:java.io.IOException:(startline 120707)EOF 在 org.apache.commons.csv.CSVParser$1.getNextRecord(CSVParser.java :530) at org.apache.commons.csv.CSVParser$1.hasNext(CSVParser.java:540) at com.ids.dam.pim.validation.CSVFileReaderApache.readFileAsListOfList(CSVFileReaderApache.java:61) at com.ids.dam .pim.validation.CSVFileReaderApache.main(CSVFileReaderApache.java:78) 原因:java.io.IOException: (startline 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)...但我不能将附件设置为 null

有没有办法在仍然使用 RFC4180 的同时将机箱设置为空?

4

1 回答 1

1

在 CSV 中引用始终是可选的,并且可以选择引用字符作为分隔符。如果您知道您的文件使用|分隔符且没有引号,则应该以这种方式构建您的 CSVFormat。请注意,withOption(...)不会将该选项应用于当前的 csv 格式,而是返回一个与原始格式相同但设置了选项的 now 格式。来自 Apache CSVFormat javadoc

public CSVFormat withQuoteMode(QuoteMode quoteModePolicy)

返回一个新的 CSVFormat,其格式的输出报价策略设置为指定值。
...

返回: 一个新的 CSVFormat等于 this 但具有指定的报价策略

你应该使用:

    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);
    }
于 2018-05-07T15:53:46.323 回答