将文件读入列表中,每个元素表示文件的一行。

5
在Clojure中,我如何将文件读入序列中,其中每行都是序列中的一个元素。因此,我想查看函数get-lines的定义,以便我可以执行以下操作:
(def lines (get-lines "test.txt"))

并且lines是一个非惰性序列。

3个回答

12

备选实现:

(require ['clojure.string :as 'str])

(defn get-lines [file]
  (str/split-lines (slurp file)))

这个函数返回一个结果向量而不是一个序列。

如果你没有使用 1.3 版本,就需要使用 clojure.contrib.string 库。


10

如果您想将延迟序列转换为非延迟序列,可以使用doall函数,示例如下:

(use 'clojure.java.io)

(defn get-lines [fname]
  (with-open [r (reader fname)]
    (doall (line-seq r))))

2
您可以使用line-seq。下面是一个快速示例:
(ns your.project
  (:require [clojure.java.io :as io]))

(defn count-lines [filename]
  (with-open [rdr (io/reader filename)]
    (count (line-seq rdr))))

请注意,line-seq惰性求值的。在读取器关闭之后,您必须小心不要消耗序列。以下代码将无法正常工作:
(def lines (with-open [rdr (io/reader "some-file")]
             (line-seq rdr)))

(println (first lines))

第一个例子有效是因为count不是惰性的。
如果你想对这些行执行某些(具有副作用的)操作,你可能会发现doseq最有用:
;; copy every "short" line in file
(with-open [rdr (io/reader from)
            wrt (io/writer to)]
  (binding [*out* wrt]
    (doseq [line (line-seq rdr) :when (< (count line) 10)]
      (println line))))

“doall” 是我正在寻找的关键字。我需要一个在 with-open 关闭文件后仍然完好可用的列表。 - ftravers

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接