clojure 1.3에서 파일을 읽고 쓰는 "추천 된"방법을 알고 싶습니다.
- 전체 파일을 읽는 방법
- 파일을 한 줄씩 읽는 방법
- 새 파일을 작성하는 방법
- 기존 파일에 줄을 추가하는 방법
clojure 1.3에서 파일을 읽고 쓰는 "추천 된"방법을 알고 싶습니다.
답변:
우리가 여기서 이진 파일이 아닌 텍스트 파일 만하고 있다고 가정합니다.
1 번 : 전체 파일을 메모리로 읽는 방법
(slurp "/tmp/test.txt")
정말 큰 파일 일 때는 권장하지 않습니다.
번호 2 : 파일을 한 줄씩 읽는 방법
(use 'clojure.java.io)
(with-open [rdr (reader "/tmp/test.txt")]
(doseq [line (line-seq rdr)]
(println line)))
with-open
매크로 리더 본체의 단부에서 폐쇄되어 처리한다. reader 함수는 문자열 (URL 등도 가능)을로 강제 변환합니다 BufferedReader
. line-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
. Writer는 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)
추신 : 다른 것을 읽지 않고 파일을 읽고 쓰는 사실에 대해 더 명확하게 설명하기 위해 먼저 File 객체를 만든 다음 BufferedReader
또는 Writer 로 강제 변환 할 수 있습니다 .
(reader (file "/tmp/test.txt"))
;; or
(writer (file "tmp/test.txt"))
파일 함수는 clojure.java.io에도 있습니다.
PS2 : 때로는 현재 디렉토리 ( ".")가 무엇인지 쉽게 볼 수 있습니다. 두 가지 방법으로 절대 경로를 얻을 수 있습니다.
(System/getProperty "user.dir")
또는
(-> (java.io.File. ".") .getAbsolutePath)
(with-open [rdr (reader "/tmp/test.txt")] (line-seq rdr))
수율 IOException Stream closed
입니다. 무엇을해야합니까? 그러나 @satyagraha의 답변으로 좋은 결과를 얻고 있습니다.
(with-open [rdr (reader "/tmp/test.txt")] (doall (line-seq rdr)))
doseq
반환 시간 nil
이 될 수 있습니다.
파일이 메모리에 맞는 경우 slurp 및 spit으로 파일을 읽고 쓸 수 있습니다.
(def s (slurp "filename.txt"))
(이제 파일의 내용을 문자열로 포함합니다)
(spit "newfile.txt" s)
종료하지 않고 파일 내용을 쓰면 newfile.txt가 작성됩니다. 파일에 추가하고 싶다면 할 수 있습니다
(spit "filename.txt" s :append true)
파일을 줄 단위로 읽거나 쓰려면 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과 리더 / 라이터 예제의 차이점은 파일이 후자의 let 문에서 열린 상태로 유지되고 읽기 및 쓰기가 버퍼링되므로 파일을 반복해서 읽거나 쓸 때 더 효율적입니다.
자세한 내용은 다음과 같습니다. slurp spit clojure.java.io Java의 BufferedReader 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)))
defn
이 이데올로기적인 Clojure 라고 생각하지 않습니다 . 여러분 read-next-line
, 지금까지의 내가 이해, 당신의 볼 수 밖에 read-lines
기능. (let [read-next-line (fn [] ...))
대신 사용했을 수 있습니다 .