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