From 3d79fa040aa253172fef621d4a38e737e9f9a10a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Tich=C3=BD?= Date: Thu, 17 Sep 2015 17:50:34 +0200 Subject: [PATCH] Add escape-char option to write-csv --- src/clojure_csv/core.clj | 16 ++++++++++------ test/clojure_csv/test/core.clj | 8 ++++++++ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/clojure_csv/core.clj b/src/clojure_csv/core.clj index f5a523a..6e5d616 100644 --- a/src/clojure_csv/core.clj +++ b/src/clojure_csv/core.clj @@ -234,16 +234,16 @@ and quotes. The main functions are parse-csv and write-csv."} "Given a character, returns the escaped version, whether that is the same as the original character or a replacement. The return is a string or a character, but it all gets passed into str anyways." - [chr delimiter quote-char] - (if (= quote-char chr) (str quote-char quote-char) chr)) + [chr delimiter quote-char escape-char] + (if (= quote-char chr) (str escape-char quote-char) chr)) (defn- quote-and-escape "Given a string (cell), returns a new string that has any necessary quoting and escaping." - [cell delimiter quote-char force-quote] + [cell delimiter quote-char escape-char force-quote] (if (or force-quote (needs-quote? cell delimiter quote-char)) (str quote-char - (apply str (map #(escape % delimiter quote-char) + (apply str (map #(escape % delimiter quote-char escape-char) cell)) quote-char) cell)) @@ -251,10 +251,11 @@ and quotes. The main functions are parse-csv and write-csv."} (defn- quote-and-escape-row "Given a row (vector of strings), quotes and escapes any cells where that is necessary and then joins all the text into a string for that entire row." - [row delimiter quote-char force-quote] + [row delimiter quote-char escape-char force-quote] (string/join delimiter (map #(quote-and-escape % delimiter quote-char + escape-char force-quote) row))) @@ -269,15 +270,18 @@ and quotes. The main functions are parse-csv and write-csv."} for writing CSV files. Default value: \\n :quote-char - A character that is used to begin and end a quoted cell. Default value: \\\" + :escape-char - A character that is used to escape quoting. + Default value: :quote-char :force-quote - Forces every cell to be quoted (useful for Excel interop) Default value: false" - [table & {:keys [delimiter quote-char end-of-line force-quote] + [table & {:keys [delimiter quote-char escape-char end-of-line force-quote] :or {delimiter \, quote-char \" end-of-line "\n" force-quote false}}] (loop [csv-string (StringBuilder.) quoted-table (map #(quote-and-escape-row % (str delimiter) quote-char + (if (nil? escape-char) quote-char escape-char) force-quote) table)] (if (empty? quoted-table) diff --git a/test/clojure_csv/test/core.clj b/test/clojure_csv/test/core.clj index 7636bf4..299a7f7 100644 --- a/test/clojure_csv/test/core.clj +++ b/test/clojure_csv/test/core.clj @@ -84,6 +84,14 @@ (is (= "a,b\"c,d\n" (write-csv [["a", "b\"c", "d"]] :quote-char \|)))) +(deftest alternate-escape-char + (is (= "quoted:,\"escaped\"quotes\"\"\n" + (write-csv [["quoted:" "escaped\"quotes\""]] :escape-char ""))) + (is (= "quoted:,\"escaped\"\"quotes\"\"\"\n" + (write-csv [["quoted:" "escaped\"quotes\""]] :escape-char \"))) + (is (= "quoted:,\"escaped\\\"quotes\\\"\"\n" + (write-csv [["quoted:" "escaped\"quotes\""]] :escape-char \\)))) + (deftest strictness (is (thrown? Exception (dorun (parse-csv "a,b,c,\"d" :strict true)))) (is (thrown? Exception (dorun (parse-csv "a,b,c,d\"e" :strict true))))