以下是我正在使用的代码段:
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
在后续版本中引入了?
答案 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}作为转义字符。