Writing about technology, traveling, politics and more

Tuesday, December 07, 2010

Conversion utilities in Java

Since the beginning of 2010, I have been involved in AsTeRICS. This is an EU-funded project aiming to provide a software construction toolset for allowing prototyping of Assistive Technology (AT) applications. These applications should be adapted to the motor abilities of end-users.

My involvement in the project varies as a result of my main workload, which this semester includes teaching an introductory computer science course, and a postgraduate course in software engineering. Lately, a request was placed for a clear way for converting a primitive type (or string) in Java to a byte array, and back. This is required to enable a custom protocol that will allow the configuration and test module to connect remotely to the AsTeRICS middleware.

I had done something similar before, but only for integer primitive data types. After searching the web for an answer, I realized that there are some methods available but none is clear enough. I quickly realized that this functionality is "almost" built-in Java via the java.nio.ByteBuffer class. This class allows for converting primitive types such as short, int, and long to byte arrays. Scalar data types such as float and double can also be converted to byte arrays through an intermediate conversion to int and long respectively.

The resulting code is posted here, and is available for download as a Java class named ConversionUtils.
import java.nio.ByteBuffer;

public class ConversionUtils
{
    public static final byte FALSE_BITS = 0x00;
    public static final byte TRUE_BITS = 0x01;

    static public boolean booleanFromByte(final byte bits)
    {
        return bits != FALSE_BITS;
    }

    static public byte booleanToByte(final boolean b)
    {
        return b ? TRUE_BITS : FALSE_BITS;
    }

    static public short shortFromBytes(final byte [] bytes)
    {
        return ByteBuffer.wrap(bytes).getShort();
    }

    static public byte [] shortToBytes(final short s)
    {
        return new byte [] {
                (byte)(s >>> 8),
                (byte) s};
    }

    static public int intFromBytes(final byte [] bytes)
    {
        return ByteBuffer.wrap(bytes).getInt();
    }

    static public byte [] intToBytes(final int i)
    {
        return new byte [] {
                (byte)(i >>> 24),
                (byte)(i >>> 16),
                (byte)(i >>> 8),
                (byte) i};
    }

    static public long longFromBytes(final byte [] bytes)
    {
        return ByteBuffer.wrap(bytes).getLong();
    }

    static public byte [] longToBytes(final long l)
    {
        return new byte [] {
                (byte)(l >>> 56),
                (byte)(l >>> 48),
                (byte)(l >>> 40),
                (byte)(l >>> 32),
                (byte)(l >>> 24),
                (byte)(l >>> 16),
                (byte)(l >>> 8),
                (byte) l};
    }

    static public float floatFromBytes(byte [] bytes)
    {
        final int bits = intFromBytes(bytes);
        return Float.intBitsToFloat(bits);
    }

    static public byte [] floatToBytes(final float f)
    {
        int i = Float.floatToRawIntBits(f);
        return intToBytes(i);
    }

    static public byte [] doubleToBytes(final double d)
    {
        long l = Double.doubleToRawLongBits(d);
        return longToBytes(l);
    }

    static public double doubleFromBytes(byte [] bytes)
    {
        final long bits = longFromBytes(bytes);
        return Double.longBitsToDouble(bits);
    }

    static public byte [] stringToBytes(final String s)
    {
        return s.getBytes();
    }

    static public String stringFromBytes(byte [] bytes)
    {
  return new String(bytes);
    }
}

The above code can be tested using the following:
import java.nio.ByteBuffer;

public static String toString(final byte [] bits)
    {
        final StringBuffer stringBuffer = new StringBuffer(bits.length * 8);
        for(final byte b : bits)
        {
            stringBuffer.append(toString(b));
        }
        return stringBuffer.toString();
    }

    public static String toString(final byte bits)
    {
        final int displayMask = 1 << 7;
        final StringBuffer buf = new StringBuffer(8);

        byte value = bits;
        for(int c = 1; c <= 8; c++)
        {
            buf.append((value & displayMask) == 0 ? '0' : '1' );
            value <<= 1;
        }

        return buf.toString();
    }

    public static void main(String[] args)
    {
        {
            System.out.println("----------------------------------------");
            final boolean b_f = false;
            System.out.println("boolean false: " + b_f);
            final byte bits = booleanToByte(b_f);
            System.out.println("bits: " + toString(bits));
            final boolean new_b = booleanFromByte(bits);
            System.out.println("new boolean: " + new_b);
        }

        {
            System.out.println("----------------------------------------");
            final boolean b_t = true;
            System.out.println("boolean true: " + b_t);
            final byte bits = booleanToByte(b_t);
            System.out.println("bits: " + toString(bits));
            final boolean new_b = booleanFromByte(bits);
            System.out.println("new boolean: " + new_b);
        }

        {
            System.out.println("----------------------------------------");
            final short s = 123;
            System.out.println("short: " + s);
            final byte [] bytes = shortToBytes(s);
            System.out.println("byte array: " + toString(bytes));
            final short new_s = shortFromBytes(bytes);
            System.out.println("new short: " + new_s);
        }

        {
            System.out.println("----------------------------------------");
            final int i = 12345;
            System.out.println("int: " + i);
            final byte [] bytes = intToBytes(i);
            System.out.println("byte array: " + toString(bytes));
            final int new_i = intFromBytes(bytes);
            System.out.println("new int: " + new_i);
        }

        {
            System.out.println("----------------------------------------");
            final long l = 123456789012345L;
            System.out.println("long: " + l);
            final byte [] bytes = longToBytes(l);
            System.out.println("byte array: " + toString(bytes));
            final long new_l = longFromBytes(bytes);
            System.out.println("new long: " + new_l);
        }

        {
            System.out.println("----------------------------------------");
            final float f = 12345.6789e-2f;
            System.out.println("float: " + f);
            final byte [] bytes = floatToBytes(f);
            System.out.println("byte array: " + toString(bytes));
            final float new_f = floatFromBytes(bytes);
            System.out.println("new float: " + new_f);
        }

        {
            System.out.println("----------------------------------------");
            final double d = 123456789.0123456789e-7;
            System.out.println("double: " + d);
            final byte [] bytes = doubleToBytes(d);
            System.out.println("byte array: " + toString(bytes));
            final double new_d = doubleFromBytes(bytes);
            System.out.println("new double: " + new_d);
        }

        {
            System.out.println("----------------------------------------");
            final String s = "Hello World!";
            System.out.println("string: " + s);
            final byte [] bytes = stringToBytes(s);
            System.out.println("byte array: " + toString(bytes));
            final String new_s = stringFromBytes(bytes);
            System.out.println("new string: " + new_s);
        }
    }

No comments: