在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,

http://richhickey.github.com/clojure-contrib/java-utils-api.html#clojure.contrib.java-utils/as-properties

如果这是为了你自己的消费,那么我会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)))))