7

これまでのところ、私は持っています:

(:require [clojure-csv.core :as csv])
(:require [clojure.java.io :as io]))

(def csv-file (.getFile  (clojure.java.io/resource "verbs.csv")))

(defn process-csv [file]
  (with-open  [rdr  (io/reader file)]
    (csv/parse-csv rdr)))

しかし、私は得てjava.io.IOException: Stream closedいます。私はclojure-csvを使用しており、2 つのメソッドを公開していparse-csvます。

Takes a CSV as a char sequence or string, and returns a lazy sequence of vectors of strings

私が知っていると思うこと:with-open怠け者で、rdrin(csv/parse-csv rdr)))はcsvファイルの1行ですよね?

PS。私もファイルを検索したいのですが、ファイルを繰り返し開いて(遅延して読み取られている場合でも)、コンテンツ全体を検索するのは費用がかかりますか??

4

4 に答える 4

13

with-openは遅延ではありませんが、 の中で遅延を行うとwith-open、遅延アクションが のスコープ内で強制されない場合に問題が発生する可能性がありwith-openます。with-open行う必要があるのは、ブロックを終了する前にすべての遅延結果を強制することです。

(defn process-csv [file]
  (with-open [rdr (io/reader file)]
    (doall (csv/parse-csv rdr))))

この関数doallは、遅延シーケンス全体が確実に実現されるように設計されています。

入力のサイズが大きいため、リーダーを自分で閉じてから、意図した目的のために遅延を使用する (必要な結果のみを生成する) という別の可能性もあります。

(defn find-results
 [stream]
 (for [record stream
       :while (seq (first record))]
   record))

(def rdr (io/reader "verbs.csv"))
(def csv (csv/parse-csv rdr))

(def results (doall (find-results csv)))

(.close rdr)
于 2013-10-28T21:35:59.180 に答える
7

これはすでに回答されていることは知っていますが、入力の最後に到達すると自動的に閉じる明示的な遅延シーケンスを作成することによる @noisesmith と同様の解決策があります。

ファイル全体を遅延処理する場合、ハンドルを自分で明示的に管理する必要はありません。そうしないと、ハンドルの問題が発生します。

(defn lazy-read-csv
  [csv-file]
  (let [in-file (io/reader csv-file)
        csv-seq (csv/read-csv in-file)
        lazy (fn lazy [wrapped]
               (lazy-seq
                 (if-let [s (seq wrapped)]
                   (cons (first s) (lazy (rest s)))
                   (.close in-file))))]
    (lazy csv-seq)))

これは、 Eric Rochester による優れたClojure Data Analysis Cookbookからのものです。

于 2013-10-29T11:19:00.930 に答える