В Clojure 1.3, Как читать и писать в файл



Я хотел бы знать "рекомендуемый" способ чтения и записи файла в clojure 1.3 .




  1. как читать весь файл

  2. как читать файл строка за строкой

  3. Как написать новый файл

  4. как добавить строку в существующий файл

748   6  

6 ответов:

предполагая, что мы здесь делаем только текстовые файлы, а не какие-то сумасшедшие двоичные файлы.

номер 1: Как прочитать весь файл в память.

(slurp "/tmp/test.txt")

не рекомендуется, когда это действительно большой файл.

номер 2: Как читать файл построчно.

(use 'clojure.java.io)
(with-open [rdr (reader "/tmp/test.txt")]
  (doseq [line (line-seq rdr)]
    (println line)))

The with-open макрос заботится о том, чтобы считыватель был закрыт в конце корпуса. Функция чтения вызывает строку (она также может выполнять URL-адрес, и т. д.) В BufferedReader. line-seq обеспечивает ленивый seq. Требование следующего элемента ленивого seq приводит к тому, что строка считывается из считывателя.

обратите внимание, что начиная с Clojure 1.7, вы также можете использовать датчики для чтения текстовых файлов.

номер 3: Как записать в новый файл.

(use 'clojure.java.io)
(with-open [wrtr (writer "/tmp/test.txt")]
  (.write wrtr "Line to be written"))

опять with-open заботится о том, чтобы BufferedWriter закрывается в конце корпуса. Писатель принуждает строку в BufferedWriter, что вы используете использовать через Java interop:(.write wrtr "something").

вы также можете использовать spit, напротив slurp:

(spit "/tmp/test.txt" "Line to be written")

номер 4: добавьте строку к существующему файлу.

(use 'clojure.java.io)
(with-open [wrtr (writer "/tmp/test.txt" :append true)]
  (.write wrtr "Line to be appended"))

то же, что и выше, но теперь с опцией добавления.

или spit, напротив slurp:

(spit "/tmp/test.txt" "Line to be written" :append true)

PS: чтобы быть более ясным о том, что Вы читаете и пишете в файл, а не что-то еще, вы можете сначала создать файловый объект, а затем принудить его к BufferedReader или писатель:

(reader (file "/tmp/test.txt"))
;; or
(writer (file "tmp/test.txt"))

функция file также находится в clojure.java.io.

PS2: иногда это удобно, чтобы иметь возможность видеть, что текущий каталог (так ".") есть. Вы можете получить абсолютный путь двумя способами:

(System/getProperty "user.dir") 

или

(-> (java.io.File. ".") .getAbsolutePath)

если файл помещается в память, вы можете читать и записывать его с чавканьем и плевком:

(def s (slurp "filename.txt"))

(s теперь содержит содержимое файла в виде строки)

(spit "newfile.txt" s)

это создает новый файл.txt, если он не выходит и записывает содержимое файла. Если вы хотите добавить к файлу, вы можете сделать

(spit "filename.txt" s :append true)

для чтения или записи файла linewise вы бы использовали Java-ридер и писатель. Они завернуты в пространство имен 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!"

обратите внимание, что разница между примерами slurp/spit и reader / writer заключается в том, что файл остается открытым (в операторах let) в последнем, а чтение и запись буферизуются, что более эффективно при повторном чтении из / записи в файл.

вот еще информация:хлебатьвертел clojure.java.io BufferedReader Java писатель Java

Что касается вопроса 2, Иногда требуется, чтобы поток строк возвращался как объект первого класса. Чтобы получить это как ленивую последовательность, и все еще автоматически закрывать файл на EOF, я использовал эту функцию:

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

Это как читать весь файл.

Если файл находится в каталоге ресурса, вы можете сделать это :

(let [file-content-str (slurp (clojure.java.io/resource "public/myfile.txt")])

Не забудьте требовать / использовать clojure.java.io

(require '[clojure.java.io :as io])
(io/copy (io/file "/etc/passwd") \*out*\)

для чтения файла строка за строкой вам больше не нужно прибегать к взаимодействию:

(->> "data.csv"
      io/resource
      io/reader
      line-seq
      (drop 1))

предполагается, что файл данных хранится в каталоге ресурсов и что первая строка-это информация заголовка, которая может быть отброшена.

Comments

    Ничего не найдено.