【问题标题】:Clojure, java.io.Writer f and lazy seqClojure、java.io.Writer f 和惰性序列
【发布时间】:2021-05-25 04:02:34
【问题描述】:

不能使用惰性序列将数据写入文件,无论我使用什么,每次都会引发“流关闭”错误。

(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 个函数(写,写 2),但都不起作用。不知道如何使用 .write 和惰性序列,惰性 clojure 世界有什么大问题。

【问题讨论】:

    标签: clojure io lazy-sequences


    【解决方案1】:

    我稍微简化了它并让它工作。您没有显示确切的错误,因此我无法更详细地发表评论。代码如下:

    (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 一书。

    【讨论】:

    • 你的 write-2 函数看起来和我的一样...我做了一些测试,看起来我只能运行一次你和我的函数ibb.co/X8qmGgw
    • 嗯,log-to-file 是一个全局变量。将它移到 write-2 函数中,仅将文件名作为字符串传入,因此它每次都会创建一个新的 Writer。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-26
    • 2010-12-08
    • 2014-06-17
    • 1970-01-01
    • 2015-06-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多