为什么CSVWriter和CSVReader使用不同的默认转义字符?

时间:2017-09-10 10:34:18

标签: java csv opencsv

以下是我正在使用的代码段:

    StringWriter writer = new StringWriter();
    CSVWriter csvwriter = new CSVWriter(writer);
    String[] originalValues = new String[2];
    originalValues[0] = "t\\est";
    originalValues[1] = "t\\est";
    System.out.println("Original values: " + originalValues[0] +"," + originalValues[1]);
    csvwriter.writeNext(originalValues);

    csvwriter.close();
    CSVReader csvReader = new CSVReader(new StringReader(writer.toString()));
    String[] resultingValues = csvReader.readNext();
    System.out.println("Resulting values: " + resultingValues[0] +"," + resultingValues[1]);

上述代码段的输出为:

Original values: t\est,t\est
Resulting values: test,test

反斜杠(' \')字符在转换后消失了!!!

通过一些基本分析,我发现它正在发生,因为CSVReader使用Back斜杠(' \')作为默认转义字符,其中CSVWriter使用双引号( '"')作为默认转义字符。

默认行为不一致的原因是什么?

为解决上述问题,我设法找到以下两个解决方案:

1)使用空字符覆盖CSVReader的默认转义字符:

 CSVParser csvParser = new CSVParserBuilder().withEscapeChar('\0').build();
 CSVReader csvReader = new CSVReaderBuilder(new StringReader(writer.toString())).withCSVParser(csvParser).build();

2)使用严格遵循RFC4180标准的RFC4180Parser:

RFC4180Parser rfc4180Parser = new RFC4180ParserBuilder().build();
CSVReader csvReader = new CSVReaderBuilder(new StringReader(writer.toString())).withCSVParser(rfc4180Parser).build();

可以使用上述任何方法对任何其他角色造成任何副作用吗?

为什么RFC4180Parser不是默认解析器?它是否只是为了保持向后兼容性,因为RFC4180Parser在后​​续版本中引入了?

1 个答案:

答案 0 :(得分:0)

我认为我们正在寻找两种逃避方式。

1)在csv中转义双引号:

test,"Monitor 24"", Samsung"
test,"Monitor 24\", Samsung"  // Linux style

由于我们在第二个字段中有逗号,因此该字段必须用双引号括起来。然后,必须使用""\"对该字段中的任何双引号进行转义。

2) \也是general escape character,例如\t(标签)或\n(换行符)。

由于'e'不在要转义的字符列表中,因此\会被忽略并删除。

因此,如果您要写"t\\\\est",该文件将包含"t\\est"(转义反斜杠)并在阅读后显示"t\est"。或者在阅读后写"\\test"可能会显示tab"est"

为了在阅读之后保持\,你确实必须告诉解析器以某种方式忽略这些序列,但是当前行为对我来说看起来并不一致 - 实际上它们都在处理{{1}作为转义字符。