在clojure中加载configuration文件作为数据结构
clojure中是否有读取函数来parsingclojure数据结构? 我的用例是读取configuration属性文件,一个属性的值应该是一个列表。 我想能够写这个:
file.properties:
property1 = ["value1" "value2"]
并在clojure:
(load-props "file.properties")
并获取值为{property1,[“value1”“value2”]的地图
现在,我正在做下面的,具有相同的input文件“file.properties”:
(defn load-props [filename] (let [io (java.io.FileInputStream. filename) prop (java.util.Properties.)] (.load prop io) (into {} prop))) ;; returns: ;; {"property1" "[\"valu1\", \"valu2\"]"} (load-props "file.properties")
但是我无法将结果parsing为clojure的向量。 我基本上在寻找Erlang的文件:consult / 1函数。 任何想法如何做到这一点?
java.util.Properties
实现Map
因此可以非常容易地完成,而无需手动parsing属性文件:
(require 'clojure.java.io) (defn load-props [file-name] (with-open [^java.io.Reader reader (clojure.java.io/reader file-name)] (let [props (java.util.Properties.)] (.load props reader) (into {} (for [[kv] props] [(keyword k) (read-string v)]))))) (load-props "test.properties") ;=> {:property3 {:foo 100, :bar :test}, :property2 99.9, :property1 ["foo" "bar"]}
特别是,属性文件比你想象的更复杂(注释,转义等等), java.util.Properties
非常擅长加载它们。
如果你想阅读java风格的属性文件,看看戴夫雷的答案 – 虽然属性文件有很多限制。
如果您使用的是Clojure 1.5或更高版本,我build议您使用edn (Datomic中使用的可扩展数据符号),它基本上是clojure数据结构,不需要任意代码执行,并且可以为诸如实例或任意types的东西添加标签。
使用它的最简单的方法是通过读取string和slurp :
(require 'clojure.edn) (clojure.edn/read-string (slurp "filename.edn"))
而已。 请注意,只读string只读取一个variables,因此您应该将您的configuration设置为映射:
{ :property1 ["value1" "value2"] }
然后:
(require 'clojure.edn) (def config (clojure.edn/read-string (slurp "config.edn"))) (println (:property1 config))
回报
["value1" "value2"]
clojure中是否有读取函数来parsingclojure数据结构?
是。 这就是所谓的read
。 您也可以使用它来读取configuration数据。
包含一个props.clj
文件
{:property1 ["value1" 2] :property2 {:some "key"}}
可以这样读:
(ns somens.core (:require [clojure.java.io :as io]) (:import [java.io PushbackReader])) (def conf (with-open [r (io/reader "props.clj")] (read (PushbackReader. r))))
当读不受信任的来源时,可能是一个好主意,转*read-eval*
:
(def conf (binding [*read-eval* false] (with-open [r (io/reader "props.clj")] (read (PushbackReader. r)))))
要将configuration数据写回文件,您应该查看打印function,如pr
和朋友。
contrib具有读写属性的function,
如果这是为了你自己的消费,那么我会build议读/写clojure数据结构,你可以把它们打印到磁盘并阅读。
(use '[clojure.contrib.duck-streams :only (read-lines)]) (import '(java.io StringReader PushbackReader)) (defn propline->map [line] ;;property1 = ["value1" "value2"] -> { :property1 ["value1" "value2"] } (let [[key-str value-str] (seq (.split line "=")) key (keyword (.trim key-str)) value (read (PushbackReader. (StringReader. value-str)))] { key value } )) (defn load-props [filename] (reduce into (map propline->map (read-lines filename))))
DEMO
user=> (def prop (load-props "file.properties")) #'user/prop user=> (prop :property1) ["value1" "value2"] user=> ((prop :property1) 1) "value2"
UPDATE
(defn non-blank? [line] (if (re-find #"\S" line) true false)) (defn non-comment? [line] (if (re-find #"^\s*\#" line) false true)) (defn load-props [filename] (reduce into (map propline->map (filter #(and (non-blank? %)(non-comment? %)) (read-lines filename)))))