Class ByteUtils


  • public class ByteUtils
    extends java.lang.Object
    Utility methods for bit, byte, and integer manipulation and conversion. Most of these were moved here from org.bitcoinj.core.Utils.
    • Field Summary

      Fields 
      Modifier and Type Field Description
      static com.google.common.io.BaseEncoding HEX
      Deprecated.
      Use hexFormat or parseHex(String) or other available options.
      static long MAX_UNSIGNED_INTEGER
      Maximum unsigned value that can be expressed by 32 bits.
      static int MAX_UNSIGNED_SHORT
      Maximum unsigned value that can be expressed by 16 bits.
    • Constructor Summary

      Constructors 
      Constructor Description
      ByteUtils()  
    • Method Summary

      All Methods Static Methods Concrete Methods 
      Modifier and Type Method Description
      static java.util.Comparator<byte[]> arrayUnsignedComparator()
      Provides a byte array comparator.
      static byte[] bigIntegerToBytes​(java.math.BigInteger b, int numBytes)
      The regular BigInteger.toByteArray() includes the sign bit of the number and might result in an extra byte addition.
      static java.math.BigInteger bytesToBigInteger​(byte[] bytes)
      Converts an array of bytes into a positive BigInteger.
      static boolean checkBitLE​(byte[] data, int index)
      Checks if the given bit is set in data, using little endian (not the same as Java native big endian)
      static java.math.BigInteger decodeCompactBits​(long compact)
      The "compact" format is a representation of a whole number N using an unsigned 32 bit number similar to a floating point format.
      static java.math.BigInteger decodeMPI​(byte[] mpi, boolean hasLength)
      MPI encoded numbers are produced by the OpenSSL BN_bn2mpi function.
      static long encodeCompactBits​(java.math.BigInteger value)  
      static byte[] encodeMPI​(java.math.BigInteger value, boolean includeLength)
      MPI encoded numbers are produced by the OpenSSL BN_bn2mpi function.
      static java.lang.String formatHex​(byte[] bytes)  
      static byte[] parseHex​(java.lang.String string)  
      static int readInt32​(java.nio.ByteBuffer buf)
      Read 4 bytes from the byte array (starting at the offset) as signed 32-bit integer in little endian format.
      static long readInt64​(byte[] bytes, int offset)
      Read 8 bytes from the byte array (starting at the offset) as signed 64-bit integer in little endian format.
      static long readInt64​(java.nio.ByteBuffer buf)
      Read 8 bytes from the buffer as signed 64-bit integer in little endian format.
      static int readUint16​(byte[] bytes, int offset)
      Read 2 bytes from the byte array (starting at the offset) as unsigned 16-bit integer in little endian format.
      static int readUint16​(java.io.InputStream is)
      Read 2 bytes from the stream as unsigned 16-bit integer in little endian format.
      static int readUint16​(java.nio.ByteBuffer buf)
      Read 2 bytes from the buffer as unsigned 16-bit integer in little endian format.
      static int readUint16BE​(byte[] bytes, int offset)
      Read 2 bytes from the byte array (starting at the offset) as unsigned 16-bit integer in big endian format.
      static int readUint16BE​(java.nio.ByteBuffer buf)
      Read 2 bytes from the buffer as unsigned 16-bit integer in big endian format.
      static long readUint32​(byte[] bytes, int offset)
      Read 4 bytes from the byte array (starting at the offset) as unsigned 32-bit integer in little endian format.
      static long readUint32​(java.io.InputStream is)
      Read 4 bytes from the stream as unsigned 32-bit integer in little endian format.
      static long readUint32​(java.nio.ByteBuffer buf)
      Read 4 bytes from the buffer as unsigned 32-bit integer in little endian format.
      static long readUint32BE​(byte[] bytes, int offset)
      Read 4 bytes from the byte array (starting at the offset) as unsigned 32-bit integer in big endian format.
      static long readUint32BE​(java.nio.ByteBuffer buf)
      Read 4 bytes from the buffer as unsigned 32-bit integer in big endian format.
      static byte[] reverseBytes​(byte[] bytes)
      Returns a copy of the given byte array in reverse order.
      static void setBitLE​(byte[] data, int index)
      Sets the given bit in data to one, using little endian (not the same as Java native big endian)
      static void writeInt16BE​(int val, byte[] out, int offset)
      Write a 16-bit integer to a given byte array in big-endian format, starting at a given offset.
      static void writeInt16BE​(int val, java.io.OutputStream stream)
      Write a 16-bit integer to a given output stream in big-endian format.
      static java.nio.ByteBuffer writeInt16BE​(int val, java.nio.ByteBuffer buf)
      Write a 16-bit integer to a given buffer in big-endian format.
      static void writeInt16LE​(int val, byte[] out, int offset)
      Write a 16-bit integer to a given byte array in little-endian format, starting at a given offset.
      static void writeInt16LE​(int val, java.io.OutputStream stream)
      Write a 16-bit integer to a given output stream in little-endian format.
      static java.nio.ByteBuffer writeInt16LE​(int val, java.nio.ByteBuffer buf)
      Write a 16-bit integer to a given buffer in little-endian format.
      static void writeInt32BE​(long val, byte[] out, int offset)
      Write a 32-bit integer to a given byte array in big-endian format, starting at a given offset.
      static void writeInt32BE​(long val, java.io.OutputStream stream)
      Write a 32-bit integer to a given output stream in big-endian format.
      static java.nio.ByteBuffer writeInt32BE​(long val, java.nio.ByteBuffer buf)
      Write a 32-bit integer to a given buffer in big-endian format.
      static void writeInt32LE​(int val, java.io.OutputStream stream)
      Write a 32-bit integer to a given output stream in little-endian format.
      static java.nio.ByteBuffer writeInt32LE​(int val, java.nio.ByteBuffer buf)
      Write a 32-bit integer to a given buffer in little-endian format.
      static void writeInt32LE​(long val, byte[] out, int offset)
      Write a 32-bit integer to a given byte array in little-endian format, starting at a given offset.
      static void writeInt32LE​(long val, java.io.OutputStream stream)
      Write a 32-bit integer to a given output stream in little-endian format.
      static java.nio.ByteBuffer writeInt32LE​(long val, java.nio.ByteBuffer buf)
      Write a 32-bit integer to a given buffer in little-endian format.
      static void writeInt64LE​(long val, byte[] out, int offset)
      Write a 64-bit integer to a given byte array in little-endian format, starting at a given offset.
      static void writeInt64LE​(long val, java.io.OutputStream stream)
      Write a 64-bit integer to a given output stream in little-endian format.
      static java.nio.ByteBuffer writeInt64LE​(long val, java.nio.ByteBuffer buf)
      Write a 64-bit integer to a given buffer in little-endian format.
      static void writeInt64LE​(java.math.BigInteger val, java.io.OutputStream stream)
      Write a 64-bit integer to a given output stream in little-endian format.
      • Methods inherited from class java.lang.Object

        clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    • Field Detail

      • MAX_UNSIGNED_SHORT

        public static final int MAX_UNSIGNED_SHORT
        Maximum unsigned value that can be expressed by 16 bits.
      • MAX_UNSIGNED_INTEGER

        public static final long MAX_UNSIGNED_INTEGER
        Maximum unsigned value that can be expressed by 32 bits.
      • HEX

        @Deprecated
        public static final com.google.common.io.BaseEncoding HEX
        Deprecated.
        Use hexFormat or parseHex(String) or other available options.
        Hex encoding used throughout the framework. Use with ByteUtils.formatHex(byte[]) or ByteUtils.parseHex(CharSequence).
    • Constructor Detail

      • ByteUtils

        public ByteUtils()
    • Method Detail

      • formatHex

        public static java.lang.String formatHex​(byte[] bytes)
      • parseHex

        public static byte[] parseHex​(java.lang.String string)
      • bigIntegerToBytes

        public static byte[] bigIntegerToBytes​(java.math.BigInteger b,
                                               int numBytes)

        The regular BigInteger.toByteArray() includes the sign bit of the number and might result in an extra byte addition. This method removes this extra byte.

        Assuming only positive numbers, it's possible to discriminate if an extra byte is added by checking if the first element of the array is 0 (0000_0000). Due to the minimal representation provided by BigInteger, it means that the bit sign is the least significant bit 0000_0000 . Otherwise the representation is not minimal. For example, if the sign bit is 0000_0000, then the representation is not minimal due to the rightmost zero.

        This is the antagonist to bytesToBigInteger(byte[]).
        Parameters:
        b - the integer to format into a byte array
        numBytes - the desired size of the resulting byte array
        Returns:
        numBytes byte long array.
      • bytesToBigInteger

        public static java.math.BigInteger bytesToBigInteger​(byte[] bytes)
        Converts an array of bytes into a positive BigInteger. This is the antagonist to bigIntegerToBytes(BigInteger, int).
        Parameters:
        bytes - to convert into a BigInteger
        Returns:
        the converted BigInteger
      • writeInt16LE

        public static java.nio.ByteBuffer writeInt16LE​(int val,
                                                       java.nio.ByteBuffer buf)
                                                throws java.nio.BufferOverflowException
        Write a 16-bit integer to a given buffer in little-endian format.

        The value is expected as an unsigned int as per the Java Unsigned Integer API.

        Parameters:
        val - value to be written
        buf - buffer to be written into
        Returns:
        the buffer
        Throws:
        java.nio.BufferOverflowException - if the value doesn't fit the remaining buffer
      • writeInt16LE

        public static void writeInt16LE​(int val,
                                        byte[] out,
                                        int offset)
                                 throws java.lang.ArrayIndexOutOfBoundsException
        Write a 16-bit integer to a given byte array in little-endian format, starting at a given offset.

        The value is expected as an unsigned int as per the Java Unsigned Integer API.

        Parameters:
        val - value to be written
        out - buffer to be written into
        offset - offset into the buffer
        Throws:
        java.lang.ArrayIndexOutOfBoundsException - if offset points outside of the buffer, or if the value doesn't fit the remaining buffer
      • writeInt16BE

        public static java.nio.ByteBuffer writeInt16BE​(int val,
                                                       java.nio.ByteBuffer buf)
                                                throws java.nio.BufferOverflowException
        Write a 16-bit integer to a given buffer in big-endian format.

        The value is expected as an unsigned int as per the Java Unsigned Integer API.

        Parameters:
        val - value to be written
        buf - buffer to be written into
        Returns:
        the buffer
        Throws:
        java.nio.BufferOverflowException - if the value doesn't fit the remaining buffer
      • writeInt16BE

        public static void writeInt16BE​(int val,
                                        byte[] out,
                                        int offset)
                                 throws java.lang.ArrayIndexOutOfBoundsException
        Write a 16-bit integer to a given byte array in big-endian format, starting at a given offset.

        The value is expected as an unsigned int as per the Java Unsigned Integer API.

        Parameters:
        val - value to be written
        out - buffer to be written into
        offset - offset into the buffer
        Throws:
        java.lang.ArrayIndexOutOfBoundsException - if offset points outside of the buffer, or if the value doesn't fit the remaining buffer
      • writeInt32LE

        public static java.nio.ByteBuffer writeInt32LE​(int val,
                                                       java.nio.ByteBuffer buf)
                                                throws java.nio.BufferOverflowException
        Write a 32-bit integer to a given buffer in little-endian format.

        The value is expected as a signed or unsigned int. If you've got an unsigned long as per the Java Unsigned Integer API, use writeInt32LE(long, ByteBuffer).

        Parameters:
        val - value to be written
        buf - buffer to be written into
        Returns:
        the buffer
        Throws:
        java.nio.BufferOverflowException - if the value doesn't fit the remaining buffer
      • writeInt32LE

        public static java.nio.ByteBuffer writeInt32LE​(long val,
                                                       java.nio.ByteBuffer buf)
                                                throws java.nio.BufferOverflowException
        Write a 32-bit integer to a given buffer in little-endian format.

        The value is expected as an unsigned long as per the Java Unsigned Integer API.

        Parameters:
        val - value to be written
        buf - buffer to be written into
        Returns:
        the buffer
        Throws:
        java.nio.BufferOverflowException - if the value doesn't fit the remaining buffer
      • writeInt32LE

        public static void writeInt32LE​(long val,
                                        byte[] out,
                                        int offset)
                                 throws java.lang.ArrayIndexOutOfBoundsException
        Write a 32-bit integer to a given byte array in little-endian format, starting at a given offset.

        The value is expected as an unsigned long as per the Java Unsigned Integer API.

        Parameters:
        val - value to be written
        out - buffer to be written into
        offset - offset into the buffer
        Throws:
        java.lang.ArrayIndexOutOfBoundsException - if offset points outside of the buffer, or if the value doesn't fit the remaining buffer
      • writeInt32BE

        public static java.nio.ByteBuffer writeInt32BE​(long val,
                                                       java.nio.ByteBuffer buf)
                                                throws java.nio.BufferOverflowException
        Write a 32-bit integer to a given buffer in big-endian format.

        The value is expected as an unsigned long as per the Java Unsigned Integer API.

        Parameters:
        val - value to be written
        buf - buffer to be written into
        Returns:
        the buffer
        Throws:
        java.nio.BufferOverflowException - if the value doesn't fit the remaining buffer
      • writeInt32BE

        public static void writeInt32BE​(long val,
                                        byte[] out,
                                        int offset)
                                 throws java.lang.ArrayIndexOutOfBoundsException
        Write a 32-bit integer to a given byte array in big-endian format, starting at a given offset.

        The value is expected as an unsigned long as per the Java Unsigned Integer API.

        Parameters:
        val - value to be written
        out - buffer to be written into
        offset - offset into the buffer
        Throws:
        java.lang.ArrayIndexOutOfBoundsException - if offset points outside of the buffer, or if the value doesn't fit the remaining buffer
      • writeInt64LE

        public static java.nio.ByteBuffer writeInt64LE​(long val,
                                                       java.nio.ByteBuffer buf)
                                                throws java.nio.BufferOverflowException
        Write a 64-bit integer to a given buffer in little-endian format.

        The value is expected as a signed or unsigned long.

        Parameters:
        val - value to be written
        buf - buffer to be written into
        Returns:
        the buffer
        Throws:
        java.nio.BufferOverflowException - if the value doesn't fit the remaining buffer
      • writeInt64LE

        public static void writeInt64LE​(long val,
                                        byte[] out,
                                        int offset)
                                 throws java.lang.ArrayIndexOutOfBoundsException
        Write a 64-bit integer to a given byte array in little-endian format, starting at a given offset.

        The value is expected as a signed or unsigned long.

        Parameters:
        val - value to be written
        out - buffer to be written into
        offset - offset into the buffer
        Throws:
        java.lang.ArrayIndexOutOfBoundsException - if offset points outside of the buffer, or if the value doesn't fit the remaining buffer
      • writeInt16LE

        public static void writeInt16LE​(int val,
                                        java.io.OutputStream stream)
                                 throws java.io.IOException
        Write a 16-bit integer to a given output stream in little-endian format.

        The value is expected as an unsigned int as per the Java Unsigned Integer API.

        Parameters:
        val - value to be written
        stream - strean to be written into
        Throws:
        java.io.IOException - if an I/O error occurs
      • writeInt16BE

        public static void writeInt16BE​(int val,
                                        java.io.OutputStream stream)
                                 throws java.io.IOException
        Write a 16-bit integer to a given output stream in big-endian format.

        The value is expected as an unsigned int as per the Java Unsigned Integer API.

        Parameters:
        val - value to be written
        stream - strean to be written into
        Throws:
        java.io.IOException - if an I/O error occurs
      • writeInt32LE

        public static void writeInt32LE​(int val,
                                        java.io.OutputStream stream)
                                 throws java.io.IOException
        Write a 32-bit integer to a given output stream in little-endian format.

        The value is expected as a signed or unsigned int. If you've got an unsigned long as per the Java Unsigned Integer API, use writeInt32LE(long, OutputStream).

        Parameters:
        val - value to be written
        stream - stream to be written into
        Throws:
        java.io.IOException - if an I/O error occurs
      • writeInt32LE

        public static void writeInt32LE​(long val,
                                        java.io.OutputStream stream)
                                 throws java.io.IOException
        Write a 32-bit integer to a given output stream in little-endian format.

        The value is expected as an unsigned long as per the Java Unsigned Integer API.

        Parameters:
        val - value to be written
        stream - strean to be written into
        Throws:
        java.io.IOException - if an I/O error occurs
      • writeInt32BE

        public static void writeInt32BE​(long val,
                                        java.io.OutputStream stream)
                                 throws java.io.IOException
        Write a 32-bit integer to a given output stream in big-endian format.

        The value is expected as an unsigned long as per the Java Unsigned Integer API.

        Parameters:
        val - value to be written
        stream - strean to be written into
        Throws:
        java.io.IOException - if an I/O error occurs
      • writeInt64LE

        public static void writeInt64LE​(long val,
                                        java.io.OutputStream stream)
                                 throws java.io.IOException
        Write a 64-bit integer to a given output stream in little-endian format.

        The value is expected as a signed or unsigned long.

        Parameters:
        val - value to be written
        stream - strean to be written into
        Throws:
        java.io.IOException - if an I/O error occurs
      • writeInt64LE

        public static void writeInt64LE​(java.math.BigInteger val,
                                        java.io.OutputStream stream)
                                 throws java.io.IOException
        Write a 64-bit integer to a given output stream in little-endian format.

        The value is expected as an unsigned BigInteger.

        Parameters:
        val - value to be written
        stream - strean to be written into
        Throws:
        java.io.IOException - if an I/O error occurs
      • readUint16

        public static int readUint16​(java.nio.ByteBuffer buf)
                              throws java.nio.BufferUnderflowException
        Read 2 bytes from the buffer as unsigned 16-bit integer in little endian format.
        Parameters:
        buf - buffer to be read from
        Throws:
        java.nio.BufferUnderflowException - if the read value extends beyond the remaining bytes of the buffer
      • readUint16

        public static int readUint16​(byte[] bytes,
                                     int offset)
                              throws java.lang.ArrayIndexOutOfBoundsException
        Read 2 bytes from the byte array (starting at the offset) as unsigned 16-bit integer in little endian format.
        Parameters:
        bytes - buffer to be read from
        offset - offset into the buffer
        Throws:
        java.lang.ArrayIndexOutOfBoundsException - if offset points outside of the buffer, or if the read value extends beyond the remaining bytes of the buffer
      • readUint16BE

        public static int readUint16BE​(java.nio.ByteBuffer buf)
                                throws java.nio.BufferUnderflowException
        Read 2 bytes from the buffer as unsigned 16-bit integer in big endian format.
        Parameters:
        buf - buffer to be read from
        Throws:
        java.nio.BufferUnderflowException - if the read value extends beyond the remaining bytes of the buffer
      • readUint16BE

        public static int readUint16BE​(byte[] bytes,
                                       int offset)
                                throws java.lang.ArrayIndexOutOfBoundsException
        Read 2 bytes from the byte array (starting at the offset) as unsigned 16-bit integer in big endian format.
        Parameters:
        bytes - buffer to be read from
        offset - offset into the buffer
        Throws:
        java.lang.ArrayIndexOutOfBoundsException - if offset points outside of the buffer, or if the read value extends beyond the remaining bytes of the buffer
      • readUint32

        public static long readUint32​(java.nio.ByteBuffer buf)
                               throws java.nio.BufferUnderflowException
        Read 4 bytes from the buffer as unsigned 32-bit integer in little endian format.
        Parameters:
        buf - buffer to be read from
        Throws:
        java.nio.BufferUnderflowException - if the read value extends beyond the remaining bytes of the buffer
      • readInt32

        public static int readInt32​(java.nio.ByteBuffer buf)
                             throws java.nio.BufferUnderflowException
        Read 4 bytes from the byte array (starting at the offset) as signed 32-bit integer in little endian format.
        Parameters:
        buf - buffer to be read from
        Returns:
        read integer
        Throws:
        java.nio.BufferUnderflowException - if the read value extends beyond the remaining bytes of the buffer
      • readUint32

        public static long readUint32​(byte[] bytes,
                                      int offset)
                               throws java.lang.ArrayIndexOutOfBoundsException
        Read 4 bytes from the byte array (starting at the offset) as unsigned 32-bit integer in little endian format.
        Parameters:
        bytes - buffer to be read from
        offset - offset into the buffer
        Throws:
        java.lang.ArrayIndexOutOfBoundsException - if offset points outside of the buffer, or if the read value extends beyond the remaining bytes of the buffer
      • readUint32BE

        public static long readUint32BE​(java.nio.ByteBuffer buf)
                                 throws java.nio.BufferUnderflowException
        Read 4 bytes from the buffer as unsigned 32-bit integer in big endian format.
        Parameters:
        buf - buffer to be read from
        Throws:
        java.nio.BufferUnderflowException - if the read value extends beyond the remaining bytes of the buffer
      • readUint32BE

        public static long readUint32BE​(byte[] bytes,
                                        int offset)
                                 throws java.lang.ArrayIndexOutOfBoundsException
        Read 4 bytes from the byte array (starting at the offset) as unsigned 32-bit integer in big endian format.
        Parameters:
        bytes - buffer to be read from
        offset - offset into the buffer
        Throws:
        java.lang.ArrayIndexOutOfBoundsException - if offset points outside of the buffer, or if the read value extends beyond the remaining bytes of the buffer
      • readInt64

        public static long readInt64​(java.nio.ByteBuffer buf)
                              throws java.nio.BufferUnderflowException
        Read 8 bytes from the buffer as signed 64-bit integer in little endian format.
        Parameters:
        buf - buffer to be read from
        Throws:
        java.nio.BufferUnderflowException - if the read value extends beyond the remaining bytes of the buffer
      • readInt64

        public static long readInt64​(byte[] bytes,
                                     int offset)
                              throws java.lang.ArrayIndexOutOfBoundsException
        Read 8 bytes from the byte array (starting at the offset) as signed 64-bit integer in little endian format.
        Parameters:
        bytes - buffer to be read from
        offset - offset into the buffer
        Throws:
        java.lang.ArrayIndexOutOfBoundsException - if offset points outside of the buffer, or if the read value extends beyond the remaining bytes of the buffer
      • readUint16

        public static int readUint16​(java.io.InputStream is)
        Read 2 bytes from the stream as unsigned 16-bit integer in little endian format.
        Parameters:
        is - stream to be read from
      • readUint32

        public static long readUint32​(java.io.InputStream is)
        Read 4 bytes from the stream as unsigned 32-bit integer in little endian format.
        Parameters:
        is - stream to be read from
      • reverseBytes

        public static byte[] reverseBytes​(byte[] bytes)
        Returns a copy of the given byte array in reverse order.
      • decodeMPI

        public static java.math.BigInteger decodeMPI​(byte[] mpi,
                                                     boolean hasLength)
        MPI encoded numbers are produced by the OpenSSL BN_bn2mpi function. They consist of a 4 byte big endian length field, followed by the stated number of bytes representing the number in big endian format (with a sign bit).
        Parameters:
        hasLength - can be set to false if the given array is missing the 4 byte length field
      • encodeMPI

        public static byte[] encodeMPI​(java.math.BigInteger value,
                                       boolean includeLength)
        MPI encoded numbers are produced by the OpenSSL BN_bn2mpi function. They consist of a 4 byte big endian length field, followed by the stated number of bytes representing the number in big endian format (with a sign bit).
        Parameters:
        includeLength - indicates whether the 4 byte length field should be included
      • decodeCompactBits

        public static java.math.BigInteger decodeCompactBits​(long compact)

        The "compact" format is a representation of a whole number N using an unsigned 32 bit number similar to a floating point format. The most significant 8 bits are the unsigned exponent of base 256. This exponent can be thought of as "number of bytes of N". The lower 23 bits are the mantissa. Bit number 24 (0x800000) represents the sign of N. Therefore, N = (-1^sign) * mantissa * 256^(exponent-3).

        Satoshi's original implementation used BN_bn2mpi() and BN_mpi2bn(). MPI uses the most significant bit of the first byte as sign. Thus 0x1234560000 is compact 0x05123456 and 0xc0de000000 is compact 0x0600c0de. Compact 0x05c0de00 would be -0x40de000000.

        Bitcoin only uses this "compact" format for encoding difficulty targets, which are unsigned 256bit quantities. Thus, all the complexities of the sign bit and using base 256 are probably an implementation accident.

      • encodeCompactBits

        public static long encodeCompactBits​(java.math.BigInteger value)
        See Also:
        decodeCompactBits(long)
      • checkBitLE

        public static boolean checkBitLE​(byte[] data,
                                         int index)
        Checks if the given bit is set in data, using little endian (not the same as Java native big endian)
      • setBitLE

        public static void setBitLE​(byte[] data,
                                    int index)
        Sets the given bit in data to one, using little endian (not the same as Java native big endian)
      • arrayUnsignedComparator

        public static java.util.Comparator<byte[]> arrayUnsignedComparator()
        Provides a byte array comparator.
        Returns:
        A comparator for byte[]