Почему CSVWriter и CSVReader используют разные escape-символы по умолчанию?

Вот мой фрагмент кода, который я использую:

    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 использует обратную косую черту ('\') в качестве escape-символа по умолчанию, где как CSVWriter использует двойную кавычку ('"') в качестве escape-символа по умолчанию.

В чем причина этого несоответствия в поведении по умолчанию?

Чтобы решить вышеуказанную проблему, мне удалось найти следующие два решения:

1) Перезаписать управляющий символ по умолчанию в CSVReader нулевым символом:

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

2) Использование RFC4180Parser, который строго следует стандартам RFC4180:

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

Может ли использование любого из вышеперечисленных подходов вызывать побочные эффекты у любых других персонажей?

И почему RFC4180Parser не парсер по умолчанию? Это только для поддержания обратной совместимости, как RFC4180Parser познакомился в более поздних версиях?

1 ответ

Я думаю, что мы смотрим на 2 вида побега здесь.

1) Избегание двойной кавычки в CSV:

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

Поскольку у нас во втором поле запятая, это поле должно быть заключено в двойные кавычки. Любые двойные кавычки внутри этого поля должны быть экранированы, "" или же \",

2) \ также является общим экранирующим символом, например \t (вкладка) или \n (новая линия).

И с тех пор 'e' нет в списке символов, чтобы убежать, \ просто игнорируется и удаляется.

Так что, если бы вы написали "t\\\\est" файл будет содержать "t\\est" (избежал обратной косой черты) и показать "t\est" после прочтения. Или писать "\\test" вероятно, покажет tab а также "est" после прочтения.

Чтобы сохранить \ после прочтения вам действительно придется как-то сказать парсеру игнорировать эти последовательности, но текущее поведение не выглядит мне противоречивым - на самом деле они оба рассматривают \ как побег персонажа.

Другие вопросы по тегам