2011-07-07 11 views
6

Tôi đang đọc các dòng từ một tệp văn bản sử dụng (line-seq (reader "input.txt")). Bộ sưu tập này sau đó được thông qua và được chương trình của tôi sử dụng.Sử dụng `line-seq` với` reader`, khi nào tệp được đóng?

Tôi lo ngại rằng đây có thể là kiểu xấu, tuy nhiên, vì tôi không xác định tệp đóng. Tôi tưởng tượng rằng tôi không thể sử dụng (with-open (line-seq (reader "input.txt"))), vì luồng tệp sẽ có khả năng bị đóng trước khi tôi duyệt qua toàn bộ chuỗi.

Có nên tránh lazy-seq kết hợp với reader cho tệp không? Có một mô hình khác tôi nên sử dụng ở đây không?

Trả lời

15

Vì đây không thực sự có một câu trả lời rõ ràng (nó tất cả trộn vào ý kiến ​​về câu trả lời đầu tiên), đây là bản chất của nó:

(with-open [r (reader "input.txt")] 
    (doall (line-seq r))) 

Điều đó sẽ buộc toàn bộ chuỗi các dòng để được đọc và đóng tệp. Sau đó, bạn có thể chuyển kết quả của toàn bộ biểu thức đó xung quanh.

Khi giao dịch với các tập tin lớn, bạn có thể có vấn đề bộ nhớ (giữ toàn bộ chuỗi các dòng trong bộ nhớ) và đó là khi đó là một ý tưởng tốt để đảo ngược chương trình:

(with-open [r (reader "input.txt")] 
    (doall (my-program (line-seq r)))) 

Bạn có thể hoặc có thể không cần doall trong trường hợp đó, tùy thuộc vào những gì chương trình của tôi trở lại và/hoặc chương trình của tôi tiêu thụ các chuỗi lazily hay không.

0

Có vẻ như clojure.contrib.duck-streams/read-lines chỉ là những gì bạn đang tìm kiếm. read-lines đóng tệp khi không có đầu vào và trả về chuỗi giống như line-seq. Hãy thử xem mã nguồn của read-lines.

+1

clojure.contrib.duck-stream không được dùng nữa: http://clojure.github.com/clojure-contrib/#duck-streams – pauldoo

+0

@pauldoo Tôi không nhận thấy điều này. Bạn nói đúng, nhưng các hàm 'line-seq' và' read-line' sử dụng cùng một mẫu để lấy các chuỗi từ trình đọc (bởi .readLine). Chỉ cần nhìn vào chúng ([line-seq] (https://github.com/clojure/clojure/blob/f86db9cc68773dd3e4a166c1ff7b81e4a98aa602/src/clj/clojure/core.clj#L2314), [dòng đọc] (https: // github.com/clojure/clojure-contrib/blob/aa3f018f65006c78b08703e7adef04b7f39e1542/src/main/clojure/clojure/contrib/duck_streams.clj#L236)), nếu bạn muốn lười biếng, bạn có thể lấy 'read-line' vào mã nguồn của bạn. – m039

+0

@pauldoo Như tôi có thể thấy một giải pháp khác không phải là sử dụng sự lười biếng và lấy toàn bộ nội dung vào một biến hoặc chỉ sử dụng .đóng trên trình đọc. Và bạn nên sử dụng 'with-open' như thế này '(with-open [r (reader" input.txt ")] (make-smth-on-line (dòng-seq r)))'. – m039