2010-12-02 4 views
9

Quelle serait la meilleure méthode pour terminer un fichier dans Clojure? Je n'ai pas rencontré d'utilitaires qui pourraient aider à le faire, mais des idées sur la façon de construire un serait appréciée!Faire défiler un fichier dans Clojure?

Merci.

Répondre

12

Comme kotarak déclaré, vous pouvez utiliser RandomAccessFile de chercher à la fin du fichier. Malheureusement, vous devez être occupé-attendre/dormir pour les changements.

En utilisant une séquence paresseuse, vous pouvez traiter les lignes "sur la volée":

(import java.io.RandomAccessFile) 

(defn raf-seq 
    [#^RandomAccessFile raf] 
    (if-let [line (.readLine raf)] 
    (lazy-seq (cons line (raf-seq raf))) 
    (do (Thread/sleep 1000) 
     (recur raf)))) 

(defn tail-seq [input] 
    (let [raf (RandomAccessFile. input "r")] 
    (.seek raf (.length raf)) 
    (raf-seq raf))) 

; Read the next 10 lines 
(take 10 (tail-seq "/var/log/mail.log")) 

Mise à jour:

Quelque chose comme tail -f /var/log/mail.log -n 0, en utilisant doseq, de sorte que les modifications sont effectivement consommées.

(doseq [line (tail-seq "/var/log/mail.log")] (println line)) 
+0

Merci pour le pointeur! Pour une raison quelconque, cela ne semble pas agir comme prévu - les changements de fichiers ne semblent pas être détectés! – viksit

+0

(Le programme s'arrête après le premier changement de fichier) – viksit

+0

S'il vous plaît vérifier ma mise à jour: Aussi peut-être écrire dans le fichier n'est pas "ligne-buffered"? –

2

Quelque chose comme:

(take-last 10 (line-seq (clojure.contrib.io/reader "file"))) 
3

Vous pouvez utiliser RandomAccessFile chercher directement à la fin du fichier et la recherche de sauts de ligne à partir de là. Pas aussi élégant et court que l'approche take-last, mais aussi pas O(n) qui pourrait être important pour les gros fichiers.

Aucune solution pour tail -f, cependant. Une inspiration pourrait être trouvée dans JLogTailer.

Questions connexes