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

ggregory 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 480b90f  [CSV-238] Escape quotes in CLOBs.
480b90f is described below

commit 480b90febb39d7a3dd6f55d6082434ef09eb0b5f
Author: Gary Gregory <gardgreg...@gmail.com>
AuthorDate: Wed Feb 27 10:41:04 2019 -0500

    [CSV-238] Escape quotes in CLOBs.
    
    Closes #39.
---
 src/changes/changes.xml                            | 17 ++++-----
 .../java/org/apache/commons/csv/CSVFormat.java     | 40 +++++++++++++++++-----
 .../org/apache/commons/csv/CSVPrinterTest.java     |  5 ++-
 3 files changed, 45 insertions(+), 17 deletions(-)

diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 04622d9..0440fbb 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -38,14 +38,15 @@
     <title>Release Notes</title>
   </properties>
   <body>
-    <release version="1.7" date="tba" description="Feature and bug fix 
release">
-      <action issue="CSV-233" type="add" dev="ggregory" due-to="Gary 
Gregory">Add predefined CSVFormats for printing MongoDB CSV and TSV.</action>
+    <release version="1.7" date="2019-MM-DD" description="Feature and bug fix 
release (Java 8)">
+      <action issue="CSV-233" type="add" dev="ggregory" due-to="Gary 
Gregory">Add predefined CSVFormats for printing MongoDB CSV anJ TSV.</action>
       <action issue="CSV-208" type="fix" dev="ggregory" due-to="Jurrie 
Overgoor">Fix escape character for POSTGRESQL_TEXT and POSTGRESQL_CSV 
formats.</action>
       <action issue="CSV-232" type="fix" dev="ggregory" due-to="Jurrie 
Overgoor, Gary Gregory">Site link "Source Repository" does not work.</action>
       <action issue="CSV-234" type="add" dev="ggregory" due-to="Roberto 
Benedetti, Gary Gregory">Add support for java.sql.Clob.</action>
       <action issue="CSV-237" type="update" dev="ggregory" due-to="Gary 
Gregory">Update to Java 8.</action>
+      <action issue="CSV-238" type="fix" dev="ggregory" due-to="Stephen 
Olander-Waters">Escape quotes in CLOBs #39.</action>
     </release>
-    <release version="1.6" date="2018-09-22" description="Feature and bug fix 
release">
+    <release version="1.6" date="2018-09-22" description="Feature and bug fix 
release (Java 7)">
       <action issue="CSV-231" type="update" dev="britter">Add more 
documentation to CSVPrinter.</action>
       <action issue="CSV-217" type="add" dev="ggregory" due-to="Korolyov 
Alexei">Add autoFlush option for CsvPrinter. PR #24.</action>
       <action issue="CSV-219" type="fix" dev="ggregory" due-to="Zhang 
Hongda">The behavior of quote char using is not similar as Excel does when the 
first string contains CJK char(s).</action>
@@ -57,7 +58,7 @@
       <action issue="CSV-225" type="fix" dev="ggregory" due-to="Anson 
Schwabecher">Parse method should avoid creating a redundant 
BufferedReader.</action>
       <action issue="CSV-233" type="fix" dev="ggregory" due-to="Gary 
Gregory">Add predefined CSVFormats for printing MongoDB CSV and TSV.</action>
     </release>
-    <release version="1.5" date="2017-09-03" description="Feature and bug fix 
release">
+    <release version="1.5" date="2017-09-03" description="Feature and bug fix 
release (Java 7)">
       <action issue="CSV-203" type="fix" dev="ggregory" due-to="Richard 
Wheeldon, Kai Paroth">withNullString value is printed without quotes when 
QuoteMode.ALL is specified; add QuoteMode.ALL_NON_NULL. PR #17.</action>
       <action issue="CSV-194" type="fix" dev="ggregory" due-to="Marc 
Prud'hommeaux">Fix outdated comments about FileReader in CSVParser #13</action>
       <action issue="CSV-193" type="fix" dev="ggregory" due-to="Matthias 
Wiehl">Fix incorrect method name 'withFirstRowAsHeader' in user guide.</action>
@@ -72,12 +73,12 @@
       <action issue="CSV-207" type="add" dev="ggregory" due-to="Gary 
Gregory">Provide a CSV Format for printing PostgreSQL CSV and Text 
formats.</action>
       <action issue="CSV-214" type="add" dev="ggregory" due-to="Nitin 
Mahendru, Gary Gregory">Adding a placeholder in the Lexer and CSV parser to 
store the end-of-line string.</action>
     </release>
-    <release version="1.4" date="2016-05-28" description="Feature and bug fix 
release">
+    <release version="1.4" date="2016-05-28" description="Feature and bug fix 
release (Java 6)">
       <action issue="CSV-181" type="update" dev="ggregory" due-to="Gary 
Gregory">Make CSVPrinter.print(Object) GC-free.</action>
       <action issue="CSV-182" type="add" dev="ggregory" due-to="Gary 
Gregory">Allow some printing operations directly from CSVFormat.</action>
       <action issue="CSV-183" type="update" dev="ggregory">Drop ferc.gov 
tests.</action>
     </release>
-    <release version="1.3" date="2016-05-09" description="Feature and bug fix 
release">
+    <release version="1.3" date="2016-05-09" description="Feature and bug fix 
release (Java 6)">
       <action issue="CSV-179" type="add" dev="britter">Add shortcut method for 
using first record as header to CSVFormat</action>
       <action issue="CSV-180" type="add" dev="britter">Add 
withHeader(Class&lt;? extends Enum&gt;) to CSVFormat</action>
       <action issue="CSV-167" type="update" dev="sebb" due-to="Rene">Comment 
line hides next record; update Javadoc to make behaviour clear</action>
@@ -91,7 +92,7 @@
       <action issue="CSV-177" type="add" dev="ggregory" due-to="Gary 
Gregory">Support trimming leading and trailing blanks.</action>
       <action issue="CSV-178" type="add" dev="ggregory" due-to="Gary 
Gregory">Create default formats for Informix UNLOAD and UNLOAD CSV.</action>
     </release>
-    <release version="1.2" date="2015-08-24" description="Feature and bug fix 
release">
+    <release version="1.2" date="2015-08-24" description="Feature and bug fix 
release (Java 6)">
       <action issue="CSV-145" type="fix" dev="ggregory" due-to="Frank 
Ulbricht">CSVFormat.with* methods clear the header comments</action>
       <action issue="CSV-156" type="fix" dev="ggregory" due-to="Jason 
Steenstra-Pickens">Incorrect Javadoc on QuoteMode.NONE</action>
       <action issue="CSV-157" type="add" dev="ggregory">Add enum 
CSVFormat.Predefined that contains the default CSVFormat values.</action>
@@ -107,7 +108,7 @@
       <action issue="CSV-131" type="add" dev="ggregory" due-to="Holger 
Stratmann">Save positions of records to enable random access</action>
       <action issue="CSV-139" type="add" 
dev="ggregory">CSVPrinter.printRecord(ResultSet) with metadata</action>
     </release>
-    <release version="1.0" date="2014-08-14" description="First release">
+    <release version="1.0" date="2014-08-14" description="First release (Java 
6)">
       <action issue="CSV-125" type="fix" dev="britter">No longer works with 
Java 6</action>
       <action issue="CSV-122" type="fix" dev="britter" due-to="Mike 
Lewis">NullPointerException when empty header string and and null string of 
""</action>
       <action issue="CSV-117" type="update" dev="sebb">Validate format 
parameters in constructor</action>
diff --git a/src/main/java/org/apache/commons/csv/CSVFormat.java 
b/src/main/java/org/apache/commons/csv/CSVFormat.java
index 7fcf830..6f77bef 100644
--- a/src/main/java/org/apache/commons/csv/CSVFormat.java
+++ b/src/main/java/org/apache/commons/csv/CSVFormat.java
@@ -1240,8 +1240,7 @@ public final class CSVFormat implements Serializable {
             out.append(getDelimiter());
         }
         if (isQuoteCharacterSet()) {
-            // the original object is needed so can check for Number
-            printWithQuotes(reader, out, newRecord);
+            printWithQuotes(reader, out);
         } else if (isEscapeCharacterSet()) {
             printWithEscapes(reader, out);
         } else if (out instanceof Writer) {
@@ -1501,18 +1500,43 @@ public final class CSVFormat implements Serializable {
      *
      * @throws IOException
      */
-    private void printWithQuotes(final Reader reader, final Appendable out, 
final boolean newRecord)
-            throws IOException {
-        final char quoteChar = getQuoteCharacter().charValue();
+    private void printWithQuotes(final Reader reader, final Appendable out) 
throws IOException {
 
         if (getQuoteMode() == QuoteMode.NONE) {
             printWithEscapes(reader, out);
             return;
         }
 
-        out.append(quoteChar);
-        IOUtils.copy(reader, out);
-        out.append(quoteChar);
+        int pos = 0;
+
+        final char quote = getQuoteCharacter().charValue();
+        final StringBuilder builder = new 
StringBuilder(IOUtils.DEFAULT_BUFFER_SIZE);
+
+        out.append(quote);
+
+        int c;
+        while (-1 != (c = reader.read())) {
+            builder.append((char) c);
+            if (c == quote) {
+                // write out segment up until this char
+                if (pos > 0) {
+                    out.append(builder.substring(0, pos));
+                    builder.setLength(0);
+                    pos = -1;
+                }
+
+                out.append(quote);
+                out.append((char) c);
+            }
+            pos++;
+        }
+
+        // write last segment
+        if (pos > 0) {
+            out.append(builder.substring(0, pos));
+        }
+
+        out.append(quote);
     }
 
     @Override
diff --git a/src/test/java/org/apache/commons/csv/CSVPrinterTest.java 
b/src/test/java/org/apache/commons/csv/CSVPrinterTest.java
index 18856cf..6a0e3af 100644
--- a/src/test/java/org/apache/commons/csv/CSVPrinterTest.java
+++ b/src/test/java/org/apache/commons/csv/CSVPrinterTest.java
@@ -219,8 +219,11 @@ public class CSVPrinterTest {
         try (final Statement statement = connection.createStatement()) {
             statement.execute("CREATE TABLE TEST(ID INT PRIMARY KEY, NAME 
VARCHAR(255), TEXT CLOB)");
             statement.execute("insert into TEST values(1, 'r1', 'long text 
1')");
-            longText2 = StringUtils.repeat('a', (IOUtils.DEFAULT_BUFFER_SIZE * 
2) + 1);
+            longText2 = StringUtils.repeat('a', IOUtils.DEFAULT_BUFFER_SIZE - 
4);
+            longText2 += "\"\r\n\"a\"";
+            longText2 += StringUtils.repeat('a', IOUtils.DEFAULT_BUFFER_SIZE - 
1);
             statement.execute("insert into TEST values(2, 'r2', '" + longText2 
+ "')");
+            longText2 = longText2.replace("\"","\"\"");
         }
     }
 

Reply via email to