You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by se...@apache.org on 2019/06/16 20:16:21 UTC

[commons-csv] branch master updated: CSV-135 - Char escape doesn't work

This is an automated email from the ASF dual-hosted git repository.

sebb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-csv.git


The following commit(s) were added to refs/heads/master by this push:
     new f7c2ca2  CSV-135 - Char escape doesn't work
f7c2ca2 is described below

commit f7c2ca216608457071ab45d05223952a69f76d58
Author: Sebb <se...@apache.org>
AuthorDate: Sun Jun 16 21:16:17 2019 +0100

    CSV-135 - Char escape doesn't work
    
    Ensure escape chars are escaped when using quote mode
---
 .../java/org/apache/commons/csv/CSVFormat.java     | 17 +++++++++--------
 .../org/apache/commons/csv/CSVPrinterTest.java     | 22 ++++++++++++++++++++++
 2 files changed, 31 insertions(+), 8 deletions(-)

diff --git a/src/main/java/org/apache/commons/csv/CSVFormat.java b/src/main/java/org/apache/commons/csv/CSVFormat.java
index 4e5dfec..9a93311 100644
--- a/src/main/java/org/apache/commons/csv/CSVFormat.java
+++ b/src/main/java/org/apache/commons/csv/CSVFormat.java
@@ -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++;
         }
diff --git a/src/test/java/org/apache/commons/csv/CSVPrinterTest.java b/src/test/java/org/apache/commons/csv/CSVPrinterTest.java
index 75253f2..06f04a8 100644
--- a/src/test/java/org/apache/commons/csv/CSVPrinterTest.java
+++ b/src/test/java/org/apache/commons/csv/CSVPrinterTest.java
@@ -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)
+    }
 }