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();
}
}
};
这将产生您期望的输出,但我不确定它是否非常有用,因为您只是依赖输入的格式是否正确,对其进行更改会使事情变得相当复杂。
此处适当的做法是向库中添加一个额外的配置选项,允许您配置是否引用给定的列。
我从数据库中卸载了一个文件,无论列的实际内容如何,所有 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();
}
}
};
这将产生您期望的输出,但我不确定它是否非常有用,因为您只是依赖输入的格式是否正确,对其进行更改会使事情变得相当复杂。
此处适当的做法是向库中添加一个额外的配置选项,允许您配置是否引用给定的列。