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



我需要将存储在磁盘上的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)))))

以下是我如何使用clojure内置进行一般操作

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

编辑:根据Jerry101在评论中的建议更新了答案。

我不知道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))

您还应该看看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)))

由于您知道文件的.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))

快速转换解决方案可能是以下代码:

(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"))))

请注意,我刚刚剪切了Nippy v2.13.0,它现在包括一对辅助实用程序来帮助简化这个用例:freeze-to-filethaw-from-file

发布详细信息:https://github.com/ptaoussanis/nippy/releases/tag/v2.13.0

干杯!

你可以试试ClojureWerk的Buffy:https://github.com/clojurewerkz/buffy.

Buffy是一个Clojure库,用于处理二进制数据,在Clojure中编写完整的二进制协议实现,将复杂的数据结构存储在堆外缓存中,读取二进制文件,以及执行通常使用ByteBuffer执行的所有操作。

如果你的二进制数据是结构化的,这是非常巧妙的,因为你可以根据结构类型定义复杂的复合类型和帧,甚至解码UTF。

相关内容

  • 没有找到相关文章

最新更新