在clojure中加载配置文件作为数据结构

Ahm*_*med 33 configuration properties clojure

clojure中是否有读取函数来解析clojure数据结构?我的用例是读取配置属性文件,属性的一个值应该是一个列表.我希望能够写成:

file.properties:

property1 = ["value1" "value2"]
Run Code Online (Sandbox Code Playgroud)

并在clojure:

(load-props "file.properties")
Run Code Online (Sandbox Code Playgroud)

并获取值为{property1,["value1""value2"]的地图

现在,我正在使用相同的输入文件"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")
Run Code Online (Sandbox Code Playgroud)

但我无法找到将结果解析为clojure向量的方法.我基本上在寻找像Erlang的文件:consult/1函数.知道怎么做吗?

Kor*_*rny 41

如果你想阅读java风格的属性文件,请看Dave Ray的答案 - 虽然属性文件有很多限制.

如果您使用的是Clojure 1.5或更高版本,我建议您使用edn,即Datomic中使用的可扩展数据符号 - 它基本上是clojure数据结构,没有任意代码执行,并且能够为实例或任意类型之类的内容添加标记.

使用它的最简单方法是通过read-stringslurp:

(require 'clojure.edn)
(clojure.edn/read-string (slurp "filename.edn"))
Run Code Online (Sandbox Code Playgroud)

而已.请注意,read-string只读取单个变量,因此您应将配置设置为映射:

{ :property1 ["value1" "value2"] }
Run Code Online (Sandbox Code Playgroud)

然后:

(require 'clojure.edn)
(def config (clojure.edn/read-string (slurp "config.edn")))
(println (:property1 config))
Run Code Online (Sandbox Code Playgroud)

回报

["value1" "value2"]
Run Code Online (Sandbox Code Playgroud)


Dav*_*Ray 31

java.util.Properties实现Map所以这可以很容易地完成,而无需手动解析属性文件:

(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 [[k v] props] [(keyword k) (read-string v)])))))

(load-props "test.properties")
;=> {:property3 {:foo 100, :bar :test}, :property2 99.9, :property1 ["foo" "bar"]}
Run Code Online (Sandbox Code Playgroud)

特别是,属性文件比你想象的更复杂(注释,转义等等),java.util.Properties并且非常擅长加载它们.

  • 一点点简化版:(进入{}道具) (2认同)
  • 您不需要使用名为propertyid的小库来完成所有这些操作(https://github.com/michaelklishin/propertied) (2认同)

Jon*_*nas 25

clojure中是否有读取函数来解析clojure数据结构?

是.它被称为read.您还可以使用它来读取配置数据.

props.clj包含的文件

{:property1 ["value1" 2]
 :property2 {:some "key"}}
Run Code Online (Sandbox Code Playgroud)

可以这样读:

(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))))
Run Code Online (Sandbox Code Playgroud)

在阅读不受信任的来源时,最好转向*read-eval*:

(def conf (binding [*read-eval* false]
            (with-open [r (io/reader "props.clj")]
              (read (PushbackReader. r)))))
Run Code Online (Sandbox Code Playgroud)

要将配置数据写回文件,您应该查看打印功能,例如pr和朋友.

  • 请注意,因为clojure 1.5你应该使用[clojure.edn/read](http://clojure.github.io/clojure/clojure.edn-api.html#clojure.edn/read),因为read可以执行任意代码,并且[edn](https://github.com/edn-format/edn)旨在确保安全和便携. (7认同)