Search code examples
fileserializationclojurebinaryarrays

How to read a whole binary file (Nippy) into byte array in Clojure?


I need to convert Nippy data structures stored on disk into something that can be read by Nippy? Nippy uses byte arrays, so I need some way to convert the file into a byte array. I have tried

(clojure.java.io/to-byte-array (clojure.java.io/file folder-path file-path))

but this gives

java.lang.IllegalArgumentException: Value out of range for byte: ? 

Then I try:

(into-array Byte/TYPE  (map byte (slurp (clojure.java.io/file folder-path file-path)))) 

but somehow the namespace is wrong, and I can't find the right one.

To write the Nippy structures in the first place, I am using:

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

Solution

  • I'm not aware of anything built-in to Clojure that will handle this. You definitely don't want slurp because that will decode the stream contents as text.

    You could write your own method to do this, basically reading from the InputStream into a buffer and writing the buffer to a java.io.ByteArrayOutputStream. Or you could use the IOUtils class from Apache Commons IO:

     (require '[clojure.java.io :as io])
     (import '[org.apache.commons.io IOUtils])
    
     (IOUtils/toByteArray (io/input-stream file-path))
    

    You should also take a look at Nippy's thaw-from-in! and freeze-to-out! functions:

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