Clojure、java.io.Writer f 和 lazy seq

Clojure, java.io.Writer f and lazy seq

无法使用 lazy-seq 将数据写入文件,无论我使用什么,每次都会出现“流关闭”错误。

(ns logger.core
  (:gen-class)
  (:require [clojure.java.io :as io])
  (:import java.util.Date
           java.util.TimeZone
           java.text.SimpleDateFormat))

(defn -main
  "Creating new logger"
  [name]
  ())

(defn- create-dt-formatter-with-time-zone [time-format time-zone-code]
  (let [*date-format* (SimpleDateFormat. time-format)
        time-zone (TimeZone/getTimeZone time-zone-code)]
    (.setTimeZone *date-format* time-zone)
    *date-format*))

(defn date-formatter
  ([] (create-dt-formatter-with-time-zone "MM.dd HH:mm:ss" "UTC"))
  ([time-zone] (create-dt-formatter-with-time-zone "MM.dd HH:mm:ss" time-zone))
  ([time-zone time-format] (create-dt-formatter-with-time-zone time-format time-format)))

(defn date-to-string
  ([^Date date] (let [formatter (date-formatter)] (.format formatter date)))
  ([^Date date ^SimpleDateFormat formatter] (.format formatter date)))

(def my-formatter (date-formatter "UTC" "MM.dd"))

(def log-to-file (io/writer "logs/text.log" :append true))

(defn write [^java.io.Writer writer data]
  (with-open [writer writer]
    (let [date-now (date-to-string (Date.))]
        (->> data
             (map #(str date-now " " % "\n"))
             (map #(.write writer %))
             (doall)
             (.flush writer)))))


(defn write-2 [^java.io.Writer log-writer data]
  (with-open [writer log-writer]
    (let [date-now (date-to-string (Date.))]
      #_(doseq [data-row data]
          (.write writer (str date-now " " data-row "\n")))
      (doall (map #(.write writer (str date-now " " % "\n")) data)))
    (doto writer (.flush writer))))


(write-2 log-to-file ["test" "test1" "test lonmg string"])

这里有2个函数(write, write-2),但是两个都不起作用。不知道,如何将 .write 与 lazy-seq 一起使用,lazy clojure 世界中的大问题是什么。

我稍微简化了一下,让它开始工作。你没有显示确切的错误,所以我不能更详细地评论。这是代码:

(ns tst.demo.core
  (:use tupelo.core tupelo.test)
  (:require
    [clojure.java.io :as io])
  (:import
    [java.io Writer]
    [java.util Date]))

(def log-to-file (io/writer "text.log" ))

(defn write-2 [^java.io.Writer log-writer data]
  (with-open [writer log-writer]
    (let [date-now (str (Date.))]
      (doall (map #(.write writer (str date-now " " % "\n")) data)))
     (.flush ^java.io.Flushable writer)))

(dotest
  (write-2 log-to-file ["test" "test1" "test lonmg string"])
  )

它基于my favorite template project。输出:

~/expr/demo > cat text.log 
Mon Feb 22 13:39:37 PST 2021 test
Mon Feb 22 13:39:37 PST 2021 test1
Mon Feb 22 13:39:37 PST 2021 test lonmg string

如果您删除 (.flush ...) 表达式,它也有效,因为关闭会自动刷新输出(即当 with-open 表单退出时)。

请注意,您可以使用 mapv 而不是 doall 来强制立即执行。或者,将最终值包装成 (vec ...) 形式。

请参阅此 list of documentation sources,尤其是 Clojure CheatSheet 和《Getting Clojure》一书。