如何在Clojure中将整个二进制文件(Nippy)读入字节数组?

use*_*027 5 binary serialization bytearray file clojure

我需要将存储在磁盘上的Nippy数据结构转换为Nippy可以读取的内容吗?Nippy使用字节数组,所以我需要一些方法将文件转换为字节数组.我试过了

(clojure.java.io/to-byte-array (clojure.java.io/file folder-path file-path))
Run Code Online (Sandbox Code Playgroud)

但这给了

java.lang.IllegalArgumentException: Value out of range for byte: ? 
Run Code Online (Sandbox Code Playgroud)

然后我尝试:

(into-array Byte/TYPE  (map byte (slurp (clojure.java.io/file folder-path file-path)))) 
Run Code Online (Sandbox Code Playgroud)

但不知何故,名称空间是错误的,我找不到合适的名称空间.

首先要编写Nippy结构,我正在使用:

(with-open [w (clojure.java.io/output-stream file-path)]
    (.write w (nippy/freeze data)))))
Run Code Online (Sandbox Code Playgroud)

Mat*_*W-D 29

这是我如何使用clojure内置函数来完成的

(defn slurp-bytes
  "Slurp the bytes from a slurpable thing"
  [x]
  (with-open [out (java.io.ByteArrayOutputStream.)]
    (clojure.java.io/copy (clojure.java.io/input-stream x) out)
    (.toByteArray out)))
Run Code Online (Sandbox Code Playgroud)

  • 这很好,但输入流应该处于“with-open”绑定中。您可以将输入和输出绑定在同一个“with-open”中。 (2认同)

Ale*_*lex 14

我不知道Clojure内置的任何内容都可以解决这个问题.你肯定不想要,slurp因为这会将流内容解码为文本.

您可以编写自己的方法来执行此操作,基本上从InputStream缓冲区读取并将缓冲区写入java.io.ByteArrayOutputStream.或者您可以使用Apache Commons IO中的IOUtils:

 (require '[clojure.java.io :as io])
 (import '[org.apache.commons.io IOUtils])

 (IOUtils/toByteArray (io/input-stream file-path))
Run Code Online (Sandbox Code Playgroud)

你也应该看看刺骨的thaw-from-in!freeze-to-out!功能:

 (import '[java.io DataInputStream DataOutputStream])

 (with-open [w (io/output-stream file-path)]
   (nippy/freeze-to-out! (DataOutputStream. w) some-data))

 (with-open [r (io/input-stream file-path)]
   (nippy/thaw-from-in! (DataInputStream. r)))
Run Code Online (Sandbox Code Playgroud)


ɲeu*_*urɳ 6

既然你知道.length了文件,你可以分配一次,使用DataInputStreamreadFully方法.无需其他库,缓冲区副本或循环.

(defn file-to-byte-array
  [^java.io.File file]
  (let [result (byte-array (.length file))]
    (with-open [in (java.io.DataInputStream. (clojure.java.io/input-stream file))]
      (.readFully in result))
    result))
Run Code Online (Sandbox Code Playgroud)