2013-06-29 5 views
5

Gegeben ein Eingabestream Ich möchte eine Lazy-Sequenz der Daten in Form von Byte-Arrays (Chunks) erstellen. Hier ist mein Versuch:Clojure: Erstellen einer Lazy-Sequenz von Byte-Chunks aus einem Eingabestrom

(defn- read-or-nil [stream] 
    (let [buf (byte-array 2)] 
    (when-not (= -1 (.read stream buf)) 
     buf))) 

(defn byte-chunk-seq [stream] 
    (cons (read-or-nil stream) (lazy-seq (byte-chunk-seq stream)))) 

(with-open [rdr (java.io.FileInputStream. "/tmp/wut")]                                               
    (take 2 (byte-chunk-seq rdr))) 

In der letzten Anweisung, wo ich den Code bin Tests, erhalte ich ein:

IOException Stream geschlossen java.io.FileInputStream.readBytes (FileInputStream.java:-2).

Wenn ich die Aussage ändern, um ein take 1 zu sein, dann kommt es gut zurück, aber das hilft mir nicht viel. Hat jemand irgendwelche Ideen, warum das nicht funktionieren würde?

Antwort

4

Es gibt ein paar Probleme.

Erstens ist Ihre Lazy-Sequenz nicht ganz korrekt. Der ganze Körper der Funktion sollte in lazy-seq eingewickelt werden, und es sollte entweder die Nachteile weitergeben, um die Sequenz fortzusetzen, oder null, um es zu beenden.

(defn byte-chunk-seq [stream] 
    (lazy-seq (if-let [buf (read-or-nil stream)] 
       (cons buf (byte-chunk-seq stream)) 
       nil))) 

Zweitens ist take auch faul. Daher wird die Lazy-Sequenz erst dann realisiert, wenn with-open den Stream geschlossen hat. Sie können diesen Fehler vermeiden, indem Sie einen doall um die Lazy-Sequenz wickeln, um es zu realisieren, bevor der Stream geschlossen wird.

(with-open [rdr (java.io.FileInputStream. "/tmp/wut")] 
    (doall (take 2 (byte-chunk-seq rdr)))) 
Verwandte Themen