Clojure 如何从文件中反序列化记录结构,该文件已通过打印dup保存到文件中?
我有以下代码:Clojure 如何从文件中反序列化记录结构,该文件已通过打印dup保存到文件中?,clojure,Clojure,我有以下代码: (use 'clojure.java.io) (defrecord Member [id name salary role]) (defrecord Role [id name]) (def member-records (ref ())) (defn add-member [member] (dosync (alter member-records conj member))) ;;Test-data --> (def dev-r(->Role 1 "Deve
(use 'clojure.java.io)
(defrecord Member [id name salary role])
(defrecord Role [id name])
(def member-records (ref ()))
(defn add-member [member]
(dosync (alter member-records conj member)))
;;Test-data -->
(def dev-r(->Role 1 "Developer"))
(def test-member1(->Member 1 "Kirill" 70000.00 dev-r))
;;Test-data <--
(defn save-data-2-file []
(with-open [wrtr (writer "C:/Platform/Work/test.cdf")]
(print-dup @member-records wrtr)))
(defn process-line [line]
(println line))
;;Test line content
;;#BTC.pcost.Member{:id 1, :name "Kirill", :salary 70000.0, :role #BTC.pcost.Role{:id 1, :name "Developer"}})
(defn load-data-from-file []
(with-open [rdr (reader "C:/Platform/Work/test.cdf")]
(doseq [line (line-seq rdr)]
(process-line line))))
(使用“clojure.java.io”)
(defrecord成员[id名称薪资角色])
(defrecord角色[id名称])
(def成员记录(ref()))
(defn添加成员[成员]
(dosync(alter member records conj member)))
;;测试数据-->
(def dev-r(->角色1“开发人员”))
(def测试成员1(->成员1“Kirill”70000.00 dev-r))
;;测试数据您可以使用和从文件中取出记录。仅限于读取字符串的第一个表单,但是,从示例中,您只存储单个表单,作为记录列表
(defn load-data-from-file [file]
(read-string (slurp file)))
懒读
如果您需要的不止是第一个表单,或者无法将整个流读入内存,那么可以直接使用,以生成惰性读取器
(defn lazy-read
([rdr] (let [eof (Object.)] (lazy-read rdr (read rdr false eof) eof)))
([rdr data eof]
(if (not= eof data)
(cons data (lazy-seq (lazy-read rdr (read rdr false eof) eof))))))
(defn load-all-data [file]
(with-open [rdr (java.io.PushbackReader. (reader file))]
(doall (lazy-read rdr))))
(load-all-data "C:/Platform/Work/test.cdf")
安全
此外,在使用或加载代码时,最好提及安全性。您应该仅将它们与受信任的源一起使用,因为使用#=
或Java构造函数,源可以在应用程序内执行任意代码。有关详细说明,请参阅的文档
设置为false
将防止出现问题,但也会阻止重建样本中的记录。为了避免这一问题,您可以使用和函数以及白名单阅读器
(defn edn-read [eof rdr]
(clojure.edn/read {:eof eof :readers {'BTC.pcost.Role map->Role
'BTC.pcost.Member map->Member}}
rdr))
(defn lazy-edn-read
([rdr] (let [eof (Object.)] (lazy-edn-read rdr (edn-read eof rdr) eof)))
([rdr data eof]
(if (not= eof data)
(cons data (lazy-seq (lazy-edn-read rdr (edn-read eof rdr) eof))))))
(defn load-all-data [file]
(with-open [rdr (java.io.PushbackReader. (reader file))]
(doall (take-while (complement nil?) (lazy-edn-read rdr)))))
(load-all-data "C:/Platform/Work/test.cdf")
您可以使用read
此函数将从文件中读取一个对象:
(defn load-data-from-file [filename]
(with-open [rdr (java.io.PushbackReader. (reader filename))]
(read rdr)))
或者,这将从文件中读取所有对象:
(defn load-all-data-from-file [filename]
(let [eof (Object.)]
(with-open [rdr (java.io.PushbackReader. (reader filename))]
(doall
(take-while #(not= % eof)
(repeatedly #(read rdr nil eof)))))))
的API文档已阅读
这是一个小的变体,将从字符串中读取所有对象:
(defn load-all-data-from-string [string]
(let [eof (Object.)]
(with-open [rdr (-> string java.io.StringReader. java.io.PushbackReader.)]
(doall
(take-while #(not= % eof)
(repeatedly #(read rdr nil eof)))))))
据我所知,使用读取字符串
不可能做到这一点。相反,我们使用read
和java.io.StringReader