Skip to content
Clojure lib for packing and unpacking binary data using a java.util.ByteBuffer
Branch: master
Clone or download
geoffsalmon Update
link to gloss
Latest commit dee223c Jan 30, 2013
Type Name Latest commit message Commit time
Failed to load latest commit information.
src/bytebuffer add fmt-size fn. allow uppercase characters in pack's fmt string Dec 30, 2011
test/bytebuffer add fmt-size fn. allow uppercase characters in pack's fmt string Dec 30, 2011
.gitignore gitignore Dec 30, 2011
project.clj v0.2.0 Dec 29, 2011


Library for packing and unpacking binary data. Simplifies working with java.nio.ByteBuffer objects.

Handles signed and unsigned values pleasantly. Usually reading or writing unsigned fields with ByteBuffers is a pain because Java doesn't have unsigned primitives. The unsigned take-* functions here actually return a type that is one step larger than the requested type, ex. take-ushort returns an int, and take-uint returns a bigint.

See the API Docs

If you're serializing or deserializing data, you should also checkout gloss.


Use put-* and take-* functions for each data type add to and remove from a bytebuffer.

(def buff (byte-buffer 100))
(put-int buff 84)
(put-byte buff -44)
(put-byte buff -44)
(.flip buff)
(take-int buff) => 84
(take-byte buff) => -44
(take-ubyte buff) => 212 ; -44 is interpreted as 212 when read as unsigned byte

Use with-buffer to bind a default buffer and avoid passing it to every take-* and put-* function.

(let [buff (byte-buffer 100)]
  (with-buffer buff
    (put-int 10)
    (put-int 6)
    (.flip buff)
    [(take-int) (take-int)]
) => [10 6]

A more compact way to add or remove data is the pack and unpack functions, which are inspired by Python's struct module. They use simple format strings, similar to printf's, to define how fields are arranged in the buffer.

(pack buff "isbb" 123 43 23 3) ; puts an int, a short and two bytes into buff
(.flip buff)
(unpack buff "isbb") => (123 43 24 3)

Use the functions pack-bits and unpack-bits to work with bit fields within numbers.

(pack-bits 2 3 2 true 3 false 1 1) => 2r11010001

(unpack-bits 2r101011001 4 \b 1 1 2) => (10 true 1 0 1)

When parsing binary file or packet structures it's often useful to pull off a larger piece of data as a separate buffer using slice-off.

(defn parse-header [buff] ...)
(defn parse-body [buff] ...)

(let [hdr (parse-header (slice-off buff 18)) ; slice off 18 byte header
      body (parse-body (slice-off buff (:len hdr))] ; parse body

See the tests for more examples.


Either grab the source or use the jar from clojars. Version 0.2.0 works with Clojure 1.3.


Add [bytebuffer "0.2.0"] to :dependencies in project.clj.


Add this dependency


and ensure you have the following maven repository added.



Copyright (c) Geoff Salmon

Licensed under EPL 1.0

You can’t perform that action at this time.