Univocity - 即使字段不包含分隔符 char 也写出周围的引号

Univocity - writing out surrounding quotes even if field does not contain delimiter char

我从数据库中卸载了一个文件,无论列的实际内容如何,​​所有 varchar 列都用引号括起来(不幸的是,卸载过程不受我控制)。

像这样:

1,"Alex ,/,awesome/,","chan"
2,"Peter ,boring","pitt"

在 pom 中将以下代码与 univocity 2.2.3 一起使用时:

public class Sample {   

    public static void main(String[] args) throws IOException {
        BeanListProcessor<Person> rowProcessor = new BeanListProcessor<Person>(Person.class);
        CsvParserSettings parserSettings = new CsvParserSettings();
        parserSettings.setProcessor(rowProcessor);  
        parserSettings.getFormat().setDelimiter(',');
        parserSettings.getFormat().setQuote('"');
        parserSettings.getFormat().setQuoteEscape('/');     
        CsvParser parser = new CsvParser(parserSettings);
        parser.parse(new FileReader("src/main/resources/person.csv"));
        List<Person> beans = rowProcessor.getBeans();

        Writer outputWriter = new FileWriter("src/main/resources/personOut.csv", true);
        CsvWriterSettings settings = new CsvWriterSettings();
        settings.getFormat().setDelimiter(',');
        settings.getFormat().setQuote('"');
        settings.getFormat().setQuoteEscape('/');
        settings.getFormat().setCharToEscapeQuoteEscaping('[=11=]');
        settings.setRowWriterProcessor(new BeanWriterProcessor<Person>(Person.class));      
        CsvWriter writer = new CsvWriter(outputWriter, settings);
        for (Person person : beans) {
            writer.processRecord(person);
        }
        writer.close();
    }
}

只有包含定界符的列用引号括起来:

1,"Alex ,/,awesome/,",chan
2,"Peter ,boring",pitt

在 writer 设置上使用 settings.setQuoteAllFields(true); 时,所有字段都被引号包围,但现在非 varchar 字段有问题。

无论列的内容如何(例如,是否存在定界符),如何只用引号括起来自源引号的列?

想要的结果:

1,"Alex ,/,awesome/,","chan"
2,"Peter ,boring","pitt"

CSV 编写器不提供明确的机制来配置它,但您可以执行以下操作:

用这个解析:

    parserSettings.setKeepQuotes(true);
    parserSettings.setKeepEscapeSequences(true);

这两个设置将有效地作为对输入 CSV 的 "split" 操作 - 您将获得分隔符之间的全部内容。使用您的样本输入,这些值将被解析为:

1 | "Alex ,/,awesome/," | chan | 
2 | "Peter boring" | pitt | 

我使用竖线分隔上面的值,以便更容易看到结果。

现在,棘手的一点是,我不能保证这将适用于库的未来版本,因为它使用内部 API:CsvWriter 有一个 processRow您可以覆盖的方法。当您的输入值按照您希望的格式正确格式化时,您可以通过用逗号连接每行的值来将它们转储出来 "as-is"。只需执行以下操作:

CsvWriter writer = new CsvWriter(outputWriter, settings){
    @Override
    protected void processRow(Object[] row) {
        for(int i = 0; i < row.length; i++){
            Object value = row[i];
            appender.append(value.toString());
            if(i + 1 < row.length) { //not the last column
                appender.append(',');
            }
            appendValueToRow();
        }
    }
};

这将产生您期望的输出,但我不确定它是否非常有用,因为您只是依赖输入的格式是否正确,对其进行更改会使事情变得相当复杂。

此处适当的做法是向库中添加一个额外的配置选项,允许您配置是否引用给定的列。