13

Clojure 1.5 引入clojure.edn,其中包括一个读取函数,该函数需要一个PushbackReader.

如果我想阅读前五个对象,我可以这样做:

(with-open [infile (java.io.PushbackReader. (clojure.java.io/reader "foo.txt"))]
  (binding [*in* infile]
    (let [edn-seq (repeatedly clojure.edn/read)]
      (dorun (take 5 (map println edn-seq))))))

我怎样才能打印出所有的对象?考虑到其中一些可能是 nil,似乎我需要检查 EOF 或类似的东西。我想要一系列与我从中得到的对象相似的对象line-seq

4

2 回答 2

16

使用 :eof 键

http://clojure.github.com/clojure/clojure.edn-api.html

opts 是一个可以包含以下键的映射: :eof - 在文件结束时返回的值。如果未提供,eof 将引发异常。

编辑:对不起,这还不够详细!给你:

(with-open [in (java.io.PushbackReader. (clojure.java.io/reader "foo.txt"))]
  (let [edn-seq (repeatedly (partial edn/read {:eof :theend} in))]
    (dorun (map println (take-while (partial not= :theend) edn-seq)))))

应该这样做

于 2013-03-06T00:50:07.533 回答
3

我又看了一遍。这是我想出的:

(defn edn-seq
  "Returns the objects from stream as a lazy sequence."
  ([]
     (edn-seq *in*))
  ([stream]
     (edn-seq {} stream))
  ([opts stream]
     (lazy-seq (cons (clojure.edn/read opts stream) (edn-seq opts stream)))))

(defn swallow-eof
  "Ignore an EOF exception raised when consuming seq."
  [seq]
  (-> (try
        (cons (first seq) (swallow-eof (rest seq)))
        (catch java.lang.RuntimeException e
          (when-not (= (.getMessage e) "EOF while reading")
            (throw e))))
      lazy-seq))

(with-open [stream (java.io.PushbackReader. (clojure.java.io/reader "foo.txt"))]
  (dorun (map println (swallow-eof (edn-seq stream)))))

edn-seq具有与 相同的签名clojure.edn/read,并保留所有现有行为,鉴于人们可能:eof以不同方式使用该选项,我认为这一点很重要。包含 EOF 异常的单独函数似乎是一个更好的选择,尽管我不确定如何最好地捕获它,因为它显示为java.lang.RuntimeException.

于 2013-03-06T15:59:12.940 回答