In clojure, how do I read a file into a sequence where each line is one element in the sequence. So I'd like to see the definition of the function get-lines
so I could do the following:
(def lines (get-lines "test.txt"))
and lines is a non-lazy sequence.
Alternate implementation:
(require ['clojure.string :as 'str])
(defn get-lines [file]
(str/split-lines (slurp file)))
This function returns a vector of the results instead of a seq.
If you are not using 1.3, require clojure.contrib.string instead.
To convert lazy sequence to non-lazy you can use doall
like so:
(use 'clojure.java.io)
(defn get-lines [fname]
(with-open [r (reader fname)]
(doall (line-seq r))))
You could use line-seq
. A quick example:
(ns your.project
(:require [clojure.java.io :as io]))
(defn count-lines [filename]
(with-open [rdr (io/reader filename)]
(count (line-seq rdr))))
Note that line-seq
is lazy. You must be careful not to consume the sequence after the reader is closed. The following will not work:
(def lines (with-open [rdr (io/reader "some-file")]
(line-seq rdr)))
(println (first lines))
The first example works because count
isn't lazy.
If you want to do something (with side effects) with the lines you'll probably find doseq
most useful:
;; 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))))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With