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

时间:2016-10-30 11:45:19

标签: java oracle11g univocity

我从数据库中卸载了一个文件,使得所有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('\0');
        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

在编写器设置上使用settings.setQuoteAllFields(true);时,所有字段都被引号括起来,但现在非varchar字段出现问题。

如果列的内容(例如分隔符是否存在),如何仅用引号括起来自源的引号所包围的列(例如分隔符是否存在)?

期望的结果:

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

1 个答案:

答案 0 :(得分:1)

CSV编写器不提供配置此功能的显式机制,但您可以执行以下操作:

解析:

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

这两个设置将有效地作为输入CSV的“拆分”操作 - 您将获得分隔符之间的整个内容。使用您的示例输入,值将被解析为:

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

我正在使用管道来分隔上面的值,以便更容易想象出来的内容。

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

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();
        }
    }
};

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

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