2

私は次のコードを持っています:

(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))))

ファイルを読み込んだ後にレコードを再作成したいのですが、どうすれば作成できるのかわかりません。はい、テキストを解析し、解析された行の要素で構造を埋めることができることはわかっていますが、「メンバー」や「ロール」などの構造体がたくさんあるため、難しいでしょう。誰かが私にできる方法を提案できますか?

4

2 に答える 2

3

read-string、およびを使用slurpして、ファイルからレコードを引き出すことができます。read-string文字列の最初のフォームの読み取りに制限されていますが、サンプルから、レコードのリストとして単一のフォームのみを保存しています。

(defn load-data-from-file [file]
  (read-string (slurp file)))


怠惰な読書

最初のフォーム以上のものが必要な場合、またはストリーム全体をメモリに読み込めない場合は、read直接使用して遅延リーダーを作成できます。

(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")


安全

read-stringまた、またはを使用してコードをロードする際のセキュリティについても言及しておくとよいでしょうread。または Java コンストラクターを使用すると、ソースがアプリケーション内で任意のコードを実行できるため、信頼できるソースでのみ使用してください。#=詳しい説明については、 のドキュメントを参照してくださいread

に設定*read-eval*するfalseと問題は回避されますが、サンプル内のレコードの再構築も妨げられます。この問題をすべて一緒に回避するには、リーダーのホワイトリストでclojure.edn/readおよび関数を使用できます。clojure.edn/read-string

(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")
于 2013-09-22T18:33:12.673 に答える