【问题标题】:Using `line-seq` with `reader`, when is the file closed?将 `line-seq` 与 `reader` 一起使用,文件何时关闭?
【发布时间】:2011-09-30 14:31:45
【问题描述】:

我正在使用(line-seq (reader "input.txt")) 从文本文件中读取行。然后这个集合被我的程序传递并使用。

我担心这可能是不好的风格,因为我没有确定性地关闭文件。我想我不能使用(with-open (line-seq (reader "input.txt"))),因为文件流可能会在我遍历整个序列之前关闭。

是否应该避免 lazy-seqreader 一起用于文件?我应该在这里使用不同的模式吗?

【问题讨论】:

    标签: clojure io lazy-evaluation


    【解决方案1】:

    由于这并没有真正明确的答案(在第一个答案上都混入了cmets),这里是它的精髓:

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

    这将强制读取整个行序列并关闭文件。然后,您可以传递整个表达式的结果。

    在处理大文件时,您可能会遇到内存问题(将整个行序列保存在内存中),此时最好反转程序:

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

    在这种情况下,您可能需要也可能不需要 doall,具体取决于 my-program 返回的内容和/或 my-program 是否延迟使用序列。

    【讨论】:

      【解决方案2】:

      看来clojure.contrib.duck-streams/read-lines 正是您要找的。 read-lines 在没有输入时关闭文件并返回序列,就像line-seq 一样。试试看read-lines的源码。

      【讨论】:

      • clojure.contrib.duck-streams 已弃用:clojure.github.com/clojure-contrib/#duck-streams
      • @pauldoo 我没有注意到这一点。你是对的,但是函数line-seqread-line 使用相同的模式从阅读器中检索字符串(通过.readLine)。看看它们(line-seqread-line),如果你想要懒惰,你可以将read-line 加入到你的源代码中。
      • @pauldoo 正如我所看到的,另一个解决方案不是使用惰性并将整个内容抓取到一个变量中,或者只是在阅读器上使用 .close。你应该像这样使用with-open (with-open [r (reader "input.txt")] (make-smth-on-lines (line-seq r)))
      • make-smth-on-lines 周围添加一个战略性放置的doall,以防它返回一个惰性序列。如果没有doall,当序列在with-open 块之外实现时,您将遇到麻烦,因为文件已经关闭。
      • 这很好,因为我什至没有想过在with-open 块之外使用序列。我认为 io 函数旨在在 with-open 块中使用。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-23
      • 1970-01-01
      • 1970-01-01
      • 2021-08-19
      • 2018-11-26
      • 2016-05-27
      相关资源
      最近更新 更多