2014-04-11 66 views
3

我需要将存储在磁盘上的Nippy数据结构转换成Nippy可以读取的内容。 Nippy使用字节数组,所以我需要一些方法将文件转换为字节数组。我曾尝试如何在Clojure中将整个二进制文件(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)))) 

但不知何故,该命名空间是错误的,我无法找到合适的人。

要编写摆在首位的刺骨的结构,我使用:

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

回答

10

我不知道任何东西内置到Clojure中,将处理这个问题。你绝对不想要slurp,因为它会将文本的内容解码。

你可以编写自己的方法来做到这一点,基本上从InputStream读取到一个缓冲区,并将缓冲区写入java.io.ByteArrayOutputStream。或者你可以使用Apache的共享IO的IOUtils class

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

(IOUtils/toByteArray (io/input-stream file-path)) 

你也应该看看刺骨的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))) 
0

你可以给一个尝试ClojureWerk的捉鬼:https://github.com/clojurewerkz/buffy

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

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

1

快速化妆移液可能是这样的代码:

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

下面是如何使用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))) 
4

做一般既然你知道文件的.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)) 
相关问题