file - fichero - En Clojure 1.3, cómo leer y escribir un archivo
leer un file en java (5)
Me gustaría saber la forma "recomendada" de leer y escribir un archivo en clojure 1.3.
- Cómo leer todo el archivo
- Cómo leer un archivo línea por línea
- Cómo escribir un nuevo archivo
- Cómo agregar una línea a un archivo existente
Con respecto a la pregunta 2, a veces se desea que la secuencia de líneas se devuelva como un objeto de primera clase. Para obtener esto como una secuencia perezosa, y todavía tener el archivo cerrado automáticamente en EOF, utilicé esta función:
(use ''clojure.java.io)
(defn read-lines [filename]
(let [rdr (reader filename)]
(defn read-next-line []
(if-let [line (.readLine rdr)]
(cons line (lazy-seq (read-next-line)))
(.close rdr)))
(lazy-seq (read-next-line)))
)
(defn echo-file []
(doseq [line (read-lines "myfile.txt")]
(println line)))
Esta es la forma de leer todo el archivo.
Si el archivo está en el directorio de recursos, puede hacer esto:
(let [file-content-str (slurp (clojure.java.io/resource "public/myfile.txt")])
recuerda requerir / usar clojure.java.io
Si el archivo se ajusta a la memoria, puede leerlo y escribirlo con sorbos y salivazos:
(def s (slurp "filename.txt"))
(s ahora contiene el contenido de un archivo como una cadena)
(spit "newfile.txt" s)
Esto crea newfile.txt si no sale y escribe el contenido del archivo. Si desea agregar al archivo, puede hacer
(spit "filename.txt" s :append true)
Para leer o escribir un archivo en línea, usaría el lector y el escritor de Java. Están envueltos en el espacio de nombres clojure.java.io:
(ns file.test
(:require [clojure.java.io :as io]))
(let [wrtr (io/writer "test.txt")]
(.write wrtr "hello, world!/n")
(.close wrtr))
(let [wrtr (io/writer "test.txt" :append true)]
(.write wrtr "hello again!")
(.close wrtr))
(let [rdr (io/reader "test.txt")]
(println (.readLine rdr))
(println (.readLine rdr)))
; "hello, world!"
; "hello again!"
Tenga en cuenta que la diferencia entre los ejemplos slurp / spit y reader / writer es que el archivo permanece abierto (en las declaraciones let) en este último y la lectura y escritura se almacenan en búfer, por lo tanto más eficiente cuando lee / escribe repetidamente en un archivo.
Aquí hay más información: slurp spit clojure.java.io Java''s BufferedReader Escritor de Java
Suponiendo que solo estamos haciendo archivos de texto aquí y no algunas cosas locas binarias.
Número 1: cómo leer un archivo completo en la memoria.
(slurp "/tmp/test.txt")
No se recomienda cuando es un archivo realmente grande.
Número 2: cómo leer un archivo línea por línea.
(use ''clojure.java.io)
(with-open [rdr (reader "/tmp/test.txt")]
(doseq [line (line-seq rdr)]
(println line)))
La macro with-open
se ocupa de que el lector esté cerrado al final del cuerpo. La función de lector coacciona una cadena (también puede hacer una URL, etc.) en un BufferedReader
. line-seq
ofrece un seq perezoso. Exigir el siguiente elemento de los resultados de perezoso seq en una línea que se lee del lector.
Tenga en cuenta que desde Clojure 1.7 en adelante, también puede usar transducers para leer archivos de texto.
Número 3: cómo escribir en un nuevo archivo.
(use ''clojure.java.io)
(with-open [wrtr (writer "/tmp/test.txt")]
(.write wrtr "Line to be written"))
Nuevamente, with-open
se ocupa que el BufferedWriter
se cierre al final del cuerpo. Writer codifica una cadena en un BufferedWriter
, que usa use vía interoperabilidad java: (.write wrtr "something").
También puedes usar spit
, lo opuesto a slurp
:
(spit "/tmp/test.txt" "Line to be written")
Número 4: añada una línea a un archivo existente.
(use ''clojure.java.io)
(with-open [wrtr (writer "/tmp/test.txt" :append true)]
(.write wrtr "Line to be appended"))
Lo mismo que arriba, pero ahora con la opción de agregar.
O de nuevo con spit
, lo opuesto a slurp
:
(spit "/tmp/test.txt" "Line to be written" :append true)
PD: Para ser más explícito sobre el hecho de que estás leyendo y escribiendo en un archivo y no en otra cosa, primero puedes crear un objeto File y luego forzarlo en un BufferedReader
o Writer:
(reader (file "/tmp/test.txt"))
;; or
(writer (file "tmp/test.txt"))
La función de archivo también está en clojure.java.io.
PS2: a veces es útil poder ver qué es el directorio actual (así que "."). Puedes obtener el camino absoluto de dos maneras:
(System/getProperty "user.dir")
o
(-> (java.io.File. ".") .getAbsolutePath)
(require ''[clojure.java.io :as io])
(io/copy (io/file "/etc/passwd") /*out*/)