CSV-135 - Char escape doesn't work

Ensure escape chars are escaped when using quote mode
This commit is contained in:
Sebb 2019-06-16 21:16:17 +01:00
parent 53fa8ad356
commit f7c2ca2166
2 changed files with 31 additions and 8 deletions

View File

@ -1443,6 +1443,10 @@ public final class CSVFormat implements Serializable {
final char delimChar = getDelimiter();
final char quoteChar = getQuoteCharacter().charValue();
// If escape char not specified, default to the quote char
// This avoids having to keep checking whether there is an escape character
// at the cost of checking against quote twice
final char escapeChar = isEscapeCharacterSet() ? getEscapeCharacter().charValue() : quoteChar;
QuoteMode quoteModePolicy = getQuoteMode();
if (quoteModePolicy == null) {
@ -1480,7 +1484,7 @@ public final class CSVFormat implements Serializable {
} else {
while (pos < end) {
c = value.charAt(pos);
if (c == LF || c == CR || c == quoteChar || c == delimChar) {
if (c == LF || c == CR || c == quoteChar || c == delimChar || c == escapeChar) {
quote = true;
break;
}
@ -1522,14 +1526,11 @@ public final class CSVFormat implements Serializable {
// the need for encapsulation.
while (pos < end) {
final char c = value.charAt(pos);
if (c == quoteChar) {
if (c == quoteChar || c == escapeChar) {
// write out the chunk up until this point
// add 1 to the length to write out the encapsulator also
out.append(value, start, pos + 1);
// put the next starting position on the encapsulator so we will
// write it out again with the next string (effectively doubling it)
start = pos;
out.append(value, start, pos);
out.append(escapeChar); // now output the escape
start = pos; // and restart with the matched char
}
pos++;
}

View File

@ -1512,4 +1512,26 @@ public class CSVPrinterTest {
}
assertEquals(content, sb.toString());
}
private void tryFormat(List<String> l, Character quote, Character escape, String expected) throws IOException {
CSVFormat format = CSVFormat.DEFAULT.withQuote(quote).withEscape(escape).withRecordSeparator(null);
Appendable out = new StringBuilder();
CSVPrinter printer = new CSVPrinter(out, format);
printer.printRecord(l);
printer.close();
assertEquals(expected, out.toString());
}
@Test
public void testCSV135() throws IOException {
List<String> l = new LinkedList<String>();
l.add("\"\""); // ""
l.add("\\\\"); // \\
l.add("\\\"\\"); // \"\
tryFormat(l, null, null, "\"\",\\\\,\\\"\\"); // "",\\,\"\ (unchanged)
tryFormat(l, '"', null, "\"\"\"\"\"\",\\\\,\"\\\"\"\\\""); // """""",\\,"\""\" (quoted, and embedded DQ doubled)
tryFormat(l, null, '\\', "\"\",\\\\\\\\,\\\\\"\\\\"); // "",\\\\,\\"\\ (escapes escaped, not quoted)
tryFormat(l, '"', '\\', "\"\\\"\\\"\",\"\\\\\\\\\",\"\\\\\\\"\\\\\""); // "\"\"","\\\\","\\\"\\" (quoted, and embedded DQ & escape escaped)
tryFormat(l, '"', '"', "\"\"\"\"\"\",\\\\,\"\\\"\"\\\""); // """""",\\,"\""\" (quoted, embedded DQ escaped)
}
}