How do I initialize a byte array in Java?

JavaArraysByte

Java Problem Overview


I have to store some constant values (UUIDs) in byte array form in java, and I'm wondering what the best way to initialize those static arrays would be. This is how I'm currently doing it, but I feel like there must be a better way.

private static final byte[] CDRIVES = new byte[] { (byte)0xe0, 0x4f, (byte)0xd0,
    0x20, (byte)0xea, 0x3a, 0x69, 0x10, (byte)0xa2, (byte)0xd8, 0x08, 0x00, 0x2b,
    0x30, 0x30, (byte)0x9d };
private static final byte[] CMYDOCS = new byte[] { (byte)0xba, (byte)0x8a, 0x0d,
    0x45, 0x25, (byte)0xad, (byte)0xd0, 0x11, (byte)0x98, (byte)0xa8, 0x08, 0x00,
    0x36, 0x1b, 0x11, 0x03 };
private static final byte[] IEFRAME = new byte[] { (byte)0x80, 0x53, 0x1c,
    (byte)0x87, (byte)0xa0, 0x42, 0x69, 0x10, (byte)0xa2, (byte)0xea, 0x08,
    0x00, 0x2b, 0x30, 0x30, (byte)0x9d };
...
and so on

Is there anything I could use that may be less efficient, but would look cleaner? for example:

private static final byte[] CDRIVES =
    new byte[] { "0xe04fd020ea3a6910a2d808002b30309d" };

Java Solutions


Solution 1 - Java

You can use an utility function to convert from the familiar hexa string to a byte[]. When used to define a final static constant, the performance cost is irrelevant.

Since Java 17

There's now java.util.HexFormat which lets you do

byte[] CDRIVES = HexFormat.of().parseHex("e04fd020ea3a6910a2d808002b30309d");

This utility class lets you specify a format which is handy if you find other formats easier to read or when you're copy-pasting from a reference source:

byte[] CDRIVES = HexFormat.ofDelimiter(":")
    .parseHex("e0:4f:d0:20:ea:3a:69:10:a2:d8:08:00:2b:30:30:9d");

Before Java 17

I'd suggest you use the function defined by Dave L in https://stackoverflow.com/questions/140131/convert-a-string-representation-of-a-hex-dump-to-a-byte-array-using-java

byte[] CDRIVES = hexStringToByteArray("e04fd020ea3a6910a2d808002b30309d");

I insert it here for maximum readability :

public static byte[] hexStringToByteArray(String s) {
    int len = s.length();
    byte[] data = new byte[len / 2];
    for (int i = 0; i < len; i += 2) {
        data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                             + Character.digit(s.charAt(i+1), 16));
    }
    return data;
}

Solution 2 - Java

byte[] myvar = "Any String you want".getBytes();

String literals can be escaped to provide any character:

byte[] CDRIVES = "\u00e0\u004f\u00d0\u0020\u00ea\u003a\u0069\u0010\u00a2\u00d8\u0008\u0000\u002b\u0030\u0030\u009d".getBytes();

Solution 3 - Java

In Java 6, there is a method doing exactly what you want:

private static final byte[] CDRIVES = javax.xml.bind.DatatypeConverter.parseHexBinary("e04fd020ea3a6910a2d808002b30309d")

Alternatively you could use Google Guava:

import com.google.common.io.BaseEncoding;
private static final byte[] CDRIVES = BaseEncoding.base16().lowerCase().decode("E04FD020ea3a6910a2d808002b30309d".toLowerCase());

The Guava method is overkill, when you are using small arrays. But Guava has also versions that can parse input streams. This is a nice feature when dealing with big hexadecimal inputs.

Solution 4 - Java

You can use the Java UUID class to store these values, instead of byte arrays:

UUID

public UUID(long mostSigBits,
            long leastSigBits)

Constructs a new UUID using the specified data. mostSigBits is used for the most significant 64 bits of the UUID and leastSigBits becomes the least significant 64 bits of the UUID.

Solution 5 - Java

Smallest internal type, which at compile time can be assigned by unsigned hex numbers is char, as

private static final char[] CDRIVES_char = new char[] {0xe0, 0xf4, ...};

In order to have an equivalent byte array one might deploy conversions as

public static byte[] charToByteArray(char[] x)
{
	final byte[] res = new byte[x.length];
	for (int i = 0; i < x.length; i++)
	{
		res[i] = (byte) x[i];
	}
	return res;
}

public static byte[][] charToByteArray(char[][] x)
{
	final byte[][] res = new byte[x.length][];
	for (int i = 0; i < x.length; i++)
	{
		res[i] = charToByteArray(x[i]);
	}
	return res;
}

Solution 6 - Java

A solution with no libraries, dynamic length returned, unsigned integer interpretation (not two's complement)

    public static byte[] numToBytes(int num){
    if(num == 0){
        return new byte[]{};
    }else if(num < 256){
        return new byte[]{ (byte)(num) };
    }else if(num < 65536){
        return new byte[]{ (byte)(num >>> 8),(byte)num };
    }else if(num < 16777216){
        return new byte[]{ (byte)(num >>> 16),(byte)(num >>> 8),(byte)num };
    }else{ // up to 2,147,483,647
        return new byte[]{ (byte)(num >>> 24),(byte)(num >>> 16),(byte)(num >>> 8),(byte)num };
    }
}

Solution 7 - Java

You can use this utility function:

public static byte[] fromHexString(String src) {
    byte[] biBytes = new BigInteger("10" + src.replaceAll("\\s", ""), 16).toByteArray();
    return Arrays.copyOfRange(biBytes, 1, biBytes.length);
}

Unlike variants of Denys Séguret and stefan.schwetschke, it allows inserting separator symbols (spaces, tabs, etc.) into the input string, making it more readable.

Example of usage:

private static final byte[] CDRIVES
    = fromHexString("e0 4f d0 20 ea 3a 69 10 a2 d8 08 00 2b 30 30 9d");
private static final byte[] CMYDOCS
    = fromHexString("BA8A0D4525ADD01198A80800361B1103");
private static final byte[] IEFRAME
    = fromHexString("80531c87 a0426910 a2ea0800 2b30309d");

Solution 8 - Java

As far as a clean process is concerned you can use ByteArrayOutputStream object...

ByteArrayOutputStream bObj = new ByteArrayOutputStream();
bObj.reset();

//write all the values to bObj one by one using

bObj.write(byte value)

// when done you can get the byte[] using

CDRIVES = bObj.toByteArray();

//than you can repeat the similar process for CMYDOCS and IEFRAME as well,

NOTE This is not an efficient solution if you really have small array.

Solution 9 - Java

My preferred option in this circumstance is to use org.apache.commons.codec.binary.Hex which has useful APIs for converting between Stringy hex and binary. For example:

  1. Hex.decodeHex(char[] data) which throws a DecoderException if there are non-hex characters in the array, or if there are an odd number of characters.

  2. Hex.encodeHex(byte[] data) is the counterpart to the decode method above, and spits out the char[].

  3. Hex.encodeHexString(byte[] data) which converts back from a byte array to a String.

Usage: Hex.decodeHex("dd645a2564cbe648c8336d2be5eafaa6".toCharArray())

Solution 10 - Java

You can use the bouncy castle package,

Maven import,

  <dependency>
        <groupId>org.bouncycastle</groupId>
        <artifactId>bcprov-jdk15on</artifactId>
    </dependency>

Java code,

byte[] CDRIVES = Hex.decode("e04fd020ea3a6910a2d808002b30309d");

Solution 11 - Java

private static final int[] CDRIVES = new int[] {0xe0, 0xf4, ...};

and after access convert to byte.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiondficklingView Question on Stackoverflow
Solution 1 - JavaDenys SéguretView Answer on Stackoverflow
Solution 2 - JavapetmezView Answer on Stackoverflow
Solution 3 - Javastefan.schwetschkeView Answer on Stackoverflow
Solution 4 - JavaJonView Answer on Stackoverflow
Solution 5 - JavaSam GinrichView Answer on Stackoverflow
Solution 6 - JavaZMittonView Answer on Stackoverflow
Solution 7 - JavaJohn McClaneView Answer on Stackoverflow
Solution 8 - JavaAmitView Answer on Stackoverflow
Solution 9 - JavarbrtlView Answer on Stackoverflow
Solution 10 - JavaSatheshView Answer on Stackoverflow
Solution 11 - JavaFrankieView Answer on Stackoverflow