Skip to content

Instantly share code, notes, and snippets.

@pingles
Created September 22, 2011 17:01
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save pingles/1235344 to your computer and use it in GitHub Desktop.
Save pingles/1235344 to your computer and use it in GitHub Desktop.
Clojure code to convert a byte array to an integer
(defn bytes-to-int
([bytes]
(bytes-to-int bytes 0))
([bytes offset]
(reduce + 0
(map (fn [i]
(let [shift (* (- 4 1 i)
8)]
(bit-shift-left (bit-and (nth bytes (+ i offset))
0x000000FF)
shift)))
(range 0 4)))))
@gfpeltier
Copy link

Alternately, for simple bytes to number:

(defn bytes->num 
  [data]
  (reduce bit-or (map-indexed (fn [i x] (bit-shift-left (bit-and x 0x0FF) (* 8 (- (count data) i 1)))) data)))

@theronic
Copy link

theronic commented Aug 18, 2020

Here is how to do it in Java:

(import 'java.nio.ByteBuffer)

(defn bytes->num [byte-array]
  {:pre [(bytes? byte-array)]}
  (.getInt (ByteBuffer/wrap byte-array)))

Example:

(bytes->num (byte-array (map byte [0 0 1 126])))
=> 382

@SoulSloth
Copy link

SoulSloth commented Feb 17, 2022

Using Java, your going to be dealing with signed integers, also many encodings use little endian, which may cause confusion since ByteBuffer defaults to big endian always.

Here's an alternative function for little endian(don't use for unsigned):

(import 'java.nio.ByteBuffer)
(import 'java.nio.ByteOrder)

(defn bytesLE->num
  "Converts a 4 byte array in little endian to int"
  [byte-array]
  {:pre [(bytes? byte-array)]}
  ;;ByteBuffer.getInt is for 32-bit integers. Use .getShort for 16 bit and .getLong for 64 bit numbers
  (.getInt (.order (ByteBuffer/wrap byte-array) ByteOrder/LITTLE_ENDIAN)))

Example

(def my-LE-array (byte-array [0x2c 0x07 0x00 0x00]))

(bytesLE->num my-LE-array)
=> 1836

@zenfey
Copy link

zenfey commented Jan 26, 2024

I thought bytebuffer wrapping method maybe slower than reduce, but criterium benchmark shows it's nearly 5x faster for one int. When treating with an array of 32 bytes containing 8 int, I found that wrapping 8 times is far more fast than wrapping the whole byte array into one java.nio.ByteBuffer then calling (.getInt bytebuf offset) with offset equals (range 0 8). Am I missing some key properties of java.nio.Bytebuffer? Thx.

Using Java, your going to be dealing with signed integers, also many encodings use little endian, which may cause confusion since ByteBuffer defaults to big endian always.

Here's an alternative function for little endian(don't use for unsigned):

(import 'java.nio.ByteBuffer)
(import 'java.nio.ByteOrder)

(defn bytesLE->num
  "Converts a 4 byte array in little endian to int"
  [byte-array]
  {:pre [(bytes? byte-array)]}
  ;;ByteBuffer.getInt is for 32-bit integers. Use .getShort for 16 bit and .getLong for 64 bit numbers
  (.getInt (.order (ByteBuffer/wrap byte-array) ByteOrder/LITTLE_ENDIAN)))

Example

(def my-LE-array (byte-array [0x2c 0x07 0x00 0x00]))

(bytesLE->num my-LE-array)
=> 1836

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment