关于文件:字节数组上的Clojure吐痰行为

Clojure spit behaviour on byte arrays

如下代码:

1
(spit"/Users/nha/tmp/spit.txt" (.getBytes"hello"))

生成一个包含" [B @ 71e054bc""的文件,该文件与内容无关(在这种情况下为" hello"),因为这是字节数组地址的JVM表示形式。

但是,以下工作(摘自该SO帖子):

1
2
3
  (clojure.java.io/copy
   (.getBytes"hello")
   (java.io.File."/Users/nha/tmp/spit.txt"))

然后该文件包含正确的内容"你好"。

为什么spit这样表现? 有没有一种方法可以扩展它的字节行为?


此问题并非字节数组所独有。

1
2
(spit"spit.txt" (Object.))
(slurp"spit.txt")              ;; =>"java.lang.Object@90b293d"

查看spit的来源,您会发现它只是在尝试写出参数之前尝试获取字符串表示形式。

您可以尝试在写入之前将任何字节数组包装在新字符串中,但要小心选择正确的编码。

1
2
3
4
5
;; platform-dependent!
(spit"spit.txt" (String. b))

;; better
(spit"spit.txt" (String. b java.nio.charset.StandardCharsets/UTF_8))

原因是内容被传递到str

您可以通过(source spit)进行检查:

1
2
3
4
5
6
7
8
9
user=> (source spit)
(defn spit
 "Opposite of slurp.  Opens f with writer, writes content, then
  closes f. Options passed to clojure.java.io/writer."
  {:added"1.2"}
  [f content & options]
  (with-open [^java.io.Writer w (apply jio/writer f options)]
    (.write w (str content))))
;            - ^^^ - here

因此,您获得写入的字节数组的字符串表示形式

编辑:并且由于spitslurp的"反",它为您提供了一个字符串,这是有意义的并且是一致的行为