Clojure: buffered reader for loop

I have a large text file that I want to process in Clojure.
I need to process it 2 lines at a time.

I decided to use a for loop so that I could pull 2 ​​lines for each pass with the following binding (rdr is my reader):

[[line-a line-b] (partition 2 (line-seq rdr))] 

(I would be interested to know other ways to get 2 rows for each iteration of the loop, but that is not the question of my question).

When I try to get the loop to work (using a simpler binding for these tests), I see the following behavior, which I cannot explain:

Why

 (with-open [rdr (reader "path/to/file")] (for [line (line-seq rdr)] line)) 

triggers a thread exception with closure

while

 (with-open [rdr (reader "path/to/file")] (doseq [line (line-seq rdr)] (println line))) 

work?

+4
source share
1 answer

for is lazy and just returns the head of the sequence, which will ultimately read the data from the file. The file is already closed when the content is printed . you can fix this pu shell for doall

 (with-open [rdr (reader "path/to/file")] (doall (for [line (line-seq rdr)] line))) 

Although this does not affect the sequence.

here is an example function from my misc.clj that lazily closes the file at the end:

 (defn byte-seq [rdr] "create a lazy seq of bytes in a file and close the file at the end" (let [result (. rdr read)] (if (= result -1) (do (. rdr close) nil) (lazy-seq (cons result (byte-seq rdr)))))) 
+7
source

All Articles