2014-04-11 70 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)) 
相關問題