我需要将存储在磁盘上的Nippy数据结构转换为Nippy可以读取的内容吗? Nippy使用字节数组,所以我需要一些方法将文件转换为字节数组。我试过了
(clojure.java.io/to-byte-array (clojure.java.io/file folder-path file-path))
但这给出了
java.lang.IllegalArgumentException: Value out of range for byte: ?
然后我尝试:
(into-array Byte/TYPE (map byte (slurp (clojure.java.io/file folder-path file-path))))
但是某种程度上命名空间是错误的,我找不到合适的命名空间。
首先要编写Nippy结构,我正在使用:
(with-open [w (clojure.java.io/output-stream file-path)]
(.write w (nippy/freeze data)))))
答案 0 :(得分:25)
以下是我使用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)))
答案 1 :(得分:12)
我不知道Clojure内置的任何内容都可以解决这个问题。你绝对不想要slurp
,因为这会将流内容解码为文本。
您可以编写自己的方法来执行此操作,基本上从InputStream
读取到缓冲区并将缓冲区写入java.io.ByteArrayOutputStream
。或者您可以使用Apache Commons IO中的IOUtils
class:
(require '[clojure.java.io :as io])
(import '[org.apache.commons.io IOUtils])
(IOUtils/toByteArray (io/input-stream file-path))
你还应该看看Nippy的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)))
答案 2 :(得分:6)
由于您知道文件的.length
,因此您可以分配一次并使用DataInputStream
的{{1}}方法。无需额外的库,缓冲区副本或循环。
readFully
答案 3 :(得分:2)
快速换班解决方案可能就是这段代码:
(defn slurpb [is]
"Convert an input stream is to byte array"
(with-open [baos (java.io.ByteArrayOutputStream.)]
(let [ba (byte-array 2000)]
(loop [n (.read is ba 0 2000)]
(when (> n 0)
(.write baos ba 0 n)
(recur (.read is ba 0 2000))))
(.toByteArray baos))))
;;test
(String. (slurpb (java.io.ByteArrayInputStream. (.getBytes "hello"))))
答案 4 :(得分:1)
请注意,我刚刚剪切了Nippy v2.13.0,它现在包含一对帮助工具,以帮助简化此用例:freeze-to-file
和thaw-from-file
。
发布详情:https://github.com/ptaoussanis/nippy/releases/tag/v2.13.0
干杯!
答案 5 :(得分:0)
你可以尝试一下ClojureWerk的Buffy:https://github.com/clojurewerkz/buffy。
Buffy是一个Clojure库,用于处理二进制数据,在Clojure中编写完整的二进制协议实现,将复杂数据结构存储在堆外缓存中,读取二进制文件以及执行通常使用ByteBuffer执行的所有操作。
如果您的二进制数据是结构化的,它非常简洁,因为您可以根据结构类型定义复杂的复合类型和帧,甚至解码UTF。