2011-07-07 1 views
6

私は(line-seq (reader "input.txt"))を使ってテキストファイルから行を読みます。このコレクションは、私のプログラムで渡され、使用されます。`line-seq`を` reader`とともに使用すると、ファイルはいつ閉じられますか?

しかし、私は決定的にファイルを閉じていないので、これは悪いスタイルかもしれないと懸念しています。私は(with-open (line-seq (reader "input.txt")))を使うことができないと想像しています。これは、シーケンス全体を横切る前にファイルストリームが閉じられる可能性があるからです。

ファイルの場合、readerと合わせてlazy-seqを避けてください。私がここで使うはずのパターンがありますか?

答えて

15

これは本当に(それはすべての最初の答えのコメントの中に混入しています)明確な答えを持っていないので、ここでの本質だ:

読むべきラインの全配列を強制します
(with-open [r (reader "input.txt")] 
    (doall (line-seq r))) 

ファイルを閉じます。その全体表現の結果を渡すことができます。

大きなファイルを扱う、あなたはメモリの問題(メモリ内のラインの全配列を保持している)を有していてもよいし、それがプログラムを反転することをお勧めしますときだとき:

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

あなたがたりないかもしれない必要があるかもしれませんその場合、私のプログラムが何を返すのか、私のプログラムがシーケンスを遅延的に消費するかどうかによって異なります。

0

clojure.contrib.duck-streams/read-linesはあなたが探しているものです。 read-linesは入力がないときにファイルを閉じ、line-seqのようなシーケンスを返します。ソースコードread-linesを見てみてください。

+1

clojure.contrib.duck-streamsは非難されています:http://clojure.github.com/clojure-contrib/#duck-streams – pauldoo

+0

@pauldoo私はこれに気付きませんでした。あなたは正しいですが、 'line-seq'と' read-line'関数は同じパターンを使って(.readLineによる)読者から文字列を取得します。それらを見てください([line-seq](https://github.com/clojure/clojure/blob/f86db9cc68773dd3e4a166c1ff7b81e4a98aa602/src/clj/clojure/core.clj#L2314)、[read-line](https:// github.com/clojure/clojure-contrib/blob/aa3f018f65006c78b08703e7adef04b7f39e1542/src/main/clojure/clojure/contrib/duck_streams.clj#L236))、もしあなたが怠け者であれば、ソースコードに 'read-line 'をつけることができます。 – m039

+0

@pauldooもう一つの解決策は、怠惰を使用せず、変数全体にコンテンツをつかむことではなく、単に読者に.closeを使うことです。そして、このように(with-open [r(reader "input.txt")](make-smth-on-lines(line-seq r))) 'のように' with-open'を使うべきです。 – m039

関連する問題