在 Clojure 中逐字符处理文件

Jac*_*and 5 clojure

我正在 Clojure 中编写一个函数,该函数将逐个字符地处理文件。我知道 Java 的 BufferedReader 类具有读取一个字符的 read() 方法,但我是 Clojure 的新手,不确定如何使用它。目前,我只是尝试逐行处理文件,然后打印每个字符。

(defn process_file [file_path]
(with-open [reader (BufferedReader. (FileReader. file_path))]
    (let [seq (line-seq reader)]
        (doseq [item seq]
            (let [words (split item #"\s")]
                (println words))))))
Run Code Online (Sandbox Code Playgroud)

给定具有此文本输入的文件:

感激地接受国际捐赠,但我们不能就从美国境外收到的捐赠的税务处理作出任何声明。仅美国法律就淹没了我们的小员工。

我的输出如下所示:

[International donations are gratefully accepted, but we cannot make]
[any statements concerning tax treatment of donations received from]
[outside the United States.  U.S. laws alone swamp our small staff.]
Run Code Online (Sandbox Code Playgroud)

虽然我希望它看起来像:

["international" "donations" "are" .... ]
Run Code Online (Sandbox Code Playgroud)

所以我的问题是,如何将上面的函数转换为逐个字符读取?甚至,如何让它按我的预期工作?此外,任何使我的 Clojure 代码更好的提示将不胜感激。

xia*_*owl 5

(with-open [reader (clojure.java.io/reader "path/to/file")] ...
Run Code Online (Sandbox Code Playgroud)

我更喜欢这种方式来获得readerclojure 。并且character by character,您的意思是在文件访问级别中,例如,它允许您控制读取的read数量?bytes

编辑

正如@deterb指出的,让我们检查一下源代码line-seq

(defn line-seq
  "Returns the lines of text from rdr as a lazy sequence of strings.
   rdr must implement java.io.BufferedReader."
  {:added "1.0"
   :static true}
  [^java.io.BufferedReader rdr]
  (when-let [line (.readLine rdr)]
    (cons line (lazy-seq (line-seq rdr)))))
Run Code Online (Sandbox Code Playgroud)

我伪造了一个char-seq

 (defn char-seq 
   [^java.io.Reader rdr]
   (let [chr (.read rdr)]
     (if (>= chr 0)
     (cons chr (lazy-seq (char-seq rdr))))))
Run Code Online (Sandbox Code Playgroud)

我知道这char-seq会将所有字符读入内存[1],但我认为这表明您可以直接.read调用BufferedReader. 因此,您可以这样编写代码:

(let [chr (.read rdr)]
  (if (>= chr 0)
    ;do your work here
  ))
Run Code Online (Sandbox Code Playgroud)

你怎么想?

[1] 根据@dimagog的评论,char-seq没有将所有字符读入内存,这要归功于lazy-seq