【问题标题】:Clojure: buffered reader in for loopClojure:for循环中的缓冲阅读器
【发布时间】:2012-08-13 09:28:02
【问题描述】:

我想在 Clojure 中处理一个大文本文件。
我需要一次处理 2 行。

我决定使用 for 循环,因此我可以使用以下绑定为每次传递拉 2 行(rdr 是我的读者):

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

(我很想知道其他方法来为每个循环迭代获取 2 行,但这不是我的问题的重点)。

当试图让循环工作(对这些测试使用更简单的绑定)时,我看到了以下我无法解释的行为:

为什么

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

触发流关闭异常

同时

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

有效吗?

【问题讨论】:

标签: clojure


【解决方案1】:

for 是惰性的,只返回最终将从文件中读取数据的序列的头部。 当您的 repl 打印 for 的内容时,文件已经关闭。你可以修复这个将for 包裹在doall 中的pu

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

虽然这会使序列变得懒散。

这是我的 misc.clj 中的一个函数示例,它在文件末尾延迟关闭文件:

(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))))))

【讨论】:

  • (byte-seq) 看起来不错 - 您是否考虑过来自 (.rdr read) 的异常?比如说,你能得到一个编码异常并泄漏打开的流吗?
  • 是的,完全正确。如果您不阅读整个序列,它也会泄漏句柄。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-28
  • 1970-01-01
  • 2017-09-23
  • 1970-01-01
  • 2023-03-23
  • 2015-02-06
  • 2011-10-23
相关资源
最近更新 更多