Java’s Missing Byte Array Class

After 25 years, it is still surprising that Java doesn’t have a proper byte array class. There can be many reasons that the data a Java program needs to work with is in a byte array. It could be the contents of a file or MQTT message or IBM MQ message, etc. Since there is no byte array class for working with a byte array that means that every Java programmer must either write their own class or search the internet for what they need. Talk about millions of people re-inventing the wheel over and over again (probably every day for the last 25 years).

FYI: A byte array is simply an array of bytes (i.e. byte[] ). “byte” is a primitive object in Java. A Java primitive does not have any methods declared for it other than what is inherited from “java.lang.Object”. As the name implies, it is the most basic of objects.

A lot of programmers will simply convert the byte array to a String and use the methods of the String class. The first problem is that you have doubled the amount of memory being used. The second problem (but more importantly) with converting from byte array to String class is that the data may actually change. The JVM will make a best guess as to what type of data is in the byte array and potentially do a conversion based on code page, coded character set identifier and/or encoding. Hence, as your Java programming teacher said, “garbage in, garbage out”.

So, I have decided to cleanup and publish my byte array class for anyone to use. The class is called ByteArray. I really do think outside the box when I name things!!! 🙂

My ByteArray class has 40 methods that can do pretty much anything to a byte array. It can be used with any type of Java application. i.e. stand-alone, JMS, etc.

  • public byte byteAt(int index)
  • public char charAt(int index)
  • public byte[] concat(byte[] suffixArray)
  • public boolean endsWith(byte[] suffixArray)
  • public boolean equals(Object other)
  • public boolean equals(Object other, int offset)
  • public byte[] getBytes()
  • public byte[] getBytes(int beginIndex)
  • public byte[] getBytes(int beginIndex, int endIndex)
  • public int getLength()
  • public int indexOf(byte[] searchFor)
  • public int indexOf(byte[] searchFor, int fromIndex)
  • public int indexOf(byte searchFor)
  • public int indexOf(byte searchFor, int fromIndex)
  • public int indexOf(String searchFor)
  • public int indexOf(String searchFor, int fromIndex)
  • public int indexOf(char searchFor)
  • public int indexOf(char searchFor, int fromIndex)
  • public boolean isEmpty()
  • public int lastIndexOf(byte[] searchFor)
  • public int lastIndexOf(byte[] searchFor, int fromIndex)
  • public int lastIndexOf(byte searchFor)
  • public int lastIndexOf(byte searchFor, int fromIndex)
  • public int lastIndexOf(String searchFor)
  • public int lastIndexOf(String searchFor, int fromIndex)
  • public int lastIndexOf(char searchFor)
  • public int lastIndexOf(char searchFor, int fromIndex)
  • public int length()
  • public byte[] replace(char oldChar, char newChar)
  • public byte[] replace(byte oldByte, byte newByte)
  • public byte[] replace(byte[] oldByteArray, byte[] newByteArray)
  • public byte[] resize(int newSize)
  • public byte[][] split(char delimiter)
  • public byte[][] split(byte delimiter)
  • public boolean startsWith(byte[] prefix)
  • public boolean startsWith(byte[] prefix, int offset)
  • public byte[] toByteArray()
  • public char[] toCharArray()
  • public String toHexArray()
  • public String toString()

There are a couple of duplicate methods because of different naming standards in the real world. i.e. getBytes() and toByteArray() methods return the same thing and getLength() and length() methods return the same thing.

Here is a simple tester Java program that shows how to use the various methods:

/**
 * Simple program to test the various methods of the ByteArray class.
 *
 * @author Roger Lacroix, Capitalware Inc.
 * @version 1.0.0
 * @license Apache 2 License
 */
public class Test_ByteArray
{
   public Test_ByteArray()
   {
      super();

      // "Mary had a little lamb, little lamb."
      byte[] bData = { 'M', 'a', 'r', 'y', ' ', 'h', 'a', 'd', ' ', 'a', ' ', 'l', 'i', 't', 't', 'l', 'e', ' ', 'l', 'a', 'm', 'b', ',', ' ', 'l', 'i', 't', 't', 'l', 'e', ' ', 'l', 'a', 'm', 'b', '.' };
      byte[] bSearch = { 0x68, 0x61, 0x64 }; // had
      byte[] bLamb = { 0x6C, 0x61, 0x6D, 0x62 }; // lamb
      byte[] bMary = { 'M', 'a', 'r', 'y' };
      byte[] bLittle = { 'l', 'i', 't', 't', 'l', 'e' };
      byte[] bPetite = { 'p', 'e', 't', 'i', 't', 'e' };

      ByteArray ba = new ByteArray(bData);

      System.out.println("ba.charAt(20)=" + ba.charAt(20));
      System.out.println("ba.byteAt(20)=" + String.format("0x%X", ba.byteAt(20)) + "\n");

      System.out.println("new String(ba.concat(bLamb))=" + new String(ba.concat(bLamb)) + "\n");

      System.out.println("ba.endsWith(bLamb)=" + ba.endsWith(bLamb) + "\n");

      System.out.println("ba.equals(new ByteArray(bLamb))=" + ba.equals(new ByteArray(bLamb)));
      System.out.println("ba.equals(new ByteArray(bData))=" + ba.equals(new ByteArray(bData)) + "\n");

      System.out.println("new String(ba.getBytes(11))=" + new String(ba.getBytes(11)));
      System.out.println("new ByteArray(ba.getBytes(11)).toHex())=" + new ByteArray(ba.getBytes(11)).toHexArray());
      System.out.println("ba.getBytes(11,16)=" + new String(ba.getBytes(11, 16)) + "\n");

      System.out.println("ba.getLength()=" + ba.getLength());
      System.out.println("ba.length()=" + ba.length() + "\n");

      System.out.println("ba.indexOf(bSearch)=" + ba.indexOf(bSearch));
      System.out.println("ba.indexOf(0x64) [d]=" + ba.indexOf((byte) 0x64));
      System.out.println("ba.indexOf(\"lamb\")=" + ba.indexOf("lamb"));
      System.out.println("ba.indexOf('l')=" + ba.indexOf('l'));
      System.out.println("ba.indexOf('l', 20))=" + ba.indexOf('l', 20) + "\n");

      System.out.println("ba.lastIndexOf(bSearch)=" + ba.lastIndexOf(bSearch));
      System.out.println("ba.lastIndexOf(0x64) [d]=" + ba.lastIndexOf((byte) 0x64));
      System.out.println("ba.lastIndexOf(\"lamb\")=" + ba.lastIndexOf("lamb"));
      System.out.println("ba.lastIndexOf('l')=" + ba.lastIndexOf('l'));
      System.out.println("ba.lastIndexOf('l', 20))=" + ba.lastIndexOf('l', 20) + "\n");

      System.out.println("ba.isEmpty()=" + ba.isEmpty() + "\n");

      System.out.println("ba.replace('l','z')=" + new String(ba.replace('l', 'z')));
      System.out.println("ba.replace((byte)0x6C,(byte)0x7A)=" + new String(ba.replace((byte) 0x6C, (byte) 0x7A)) + "\n");
      System.out.println("ba.replace(bLittle, bPetite)=" + new String(ba.replace(bLittle, bPetite)) + "\n");

      byte[] newArray = ba.resize(111);
      System.out.println("byte[] newArray = ba.resize(111)");
      System.out.println("newArray.length=" + newArray.length + " : new String(newArray)=" + new String(newArray) + "\n");

      byte[][] newArray2 = ba.split(' ');
      for (int i = 0; i < newArray2.length; i++)
         System.out.println("new String(newArray2[" + i + "])=" + new String(newArray2[i]));
      System.out.println();

      System.out.println("ba.startsWith(bMary)=" + ba.startsWith(bMary));
      System.out.println("ba.startsWith(bLamb)=" + ba.startsWith(bLamb));
      System.out.println("ba.startsWith(bLamb,18)=" + ba.startsWith(bLamb, 18));
   }

   public static void main(String[] args)
   {
      new Test_ByteArray();
   }
}

I have generated the JavaDocs for the ByteArray class. I zipped up the JavaDocs, Test_ByteArray.java program and the ByteArray class. You can download the source code from here.

Simply copy the ByteArray class to your utility (or handler) package of your application and then start using it.

Regards,
Roger Lacroix
Capitalware Inc.

This entry was posted in HPE NonStop, IBM i (OS/400), Java, JMS, Linux, macOS (Mac OS X), Open Source, Programming, Raspberry Pi, Unix, Windows, z/OS.

3 Responses to Java’s Missing Byte Array Class