Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Writing clojure maps/arrays to a file and reading them back

I need to save clojure maps to a file and read them back later to process them.

This is what I could come up with. Is there a better way to accomplish the same thing?

user=> (def my-data (for [ a [ "Person1" "Person2" ]  b [ "Address1" "Address2"]  c   (range 10) ] {:name a :address b :index c} ))
#'user/my-data
user=> (count my-data)
40

user=> (defn write-data[xs] (with-open [wrtr (clojure.java.io/writer "my-data.txt") ]
              (doall (map #(.write wrtr (str % "\n")) xs))))
#'user/write-data

user=> (write-data my-data)

user=> (defn read-data[] (with-open [rdr (clojure.java.io/reader "my-data.txt") ]
            (doall (map #(load-string %) (line-seq rdr)))))
#'user/read-data

user=> (count (read-data))
40
like image 567
psaradhi Avatar asked Oct 02 '13 22:10

psaradhi


1 Answers

Yes - spit and prn-str for writing, slurp and read-string for reading.

user=> (def a [1 2 3 4])
#'user/a
user=> (prn-str a)
"[1 2 3 4]\n"
user=> (spit "stored-array.dat" (prn-str a))
nil

(in a new REPL session)

user=> (require 'clojure.edn)
nil
user=> (slurp "stored-array.dat")
"[1 2 3 4]\n"
user=> (clojure.edn/read-string (slurp "stored-array.dat"))
[1 2 3 4]

I used a vector for that example, but any data (e.g. maps) should work just as well.

Note that there is a read-string in the main Clojure language, but this is explicitly documented as not being safe for untrusted data, so it's better to use the version from clojure.edn.

like image 182
rkday Avatar answered Oct 15 '22 08:10

rkday