Monday, August 9, 2010

Converting a long to a byte array and back again

One thing that may not be immediately obvious is that Cassandra stores all values as a byte array. While this is not really important if your are storing a string (converting to a byte array is relatively easy) what if you need to store a date. Dates in Java are essentially of type log and represent the number of milliseconds since 1970 (or there abouts). If you want to store a date you need to convert it to a byte array and back again when going into and out of the key store. You could use serialization to achieve this, but as this article:

http://java.sun.com/developer/technicalArticles/Programming/serialization/

points out serialization can be a slow process. So, here I present two methods to convert a date to and from a byte array. I welcome comments on these, I’m sure they can be speeded up and generally be improved.

Converting to a byte array

Longs are stored as 8 bytes, so converting them is a case of masking off the bottom byte storing it in the array and then shifting the orignal number right 8 bits.

private  byte[] longToByteArray(long value)
{
byte[] buffer = new byte[8]; //longs are 8 bytes I believe
for (int i = 7; i >= 0; i--) { //fill from the right
 buffer[i]= (byte)(value & 0x00000000000000ff); //get the bottom byte
     
 //System.out.print(""+Integer.toHexString((int)buffer[i])+",");
 value=value >>> 8; //Shift the value right 8 bits
 }
return buffer;
}

Converting back from a byte array to a long


Converting back the other way we use a multiplier to convert each byte to it’s correct value. This multiplier is shifted left 8 bits each time round the loop.

private long byteArrayToLong(byte[] buffer){
long value=0;
long multiplier=1;
for (int i = 7; i >= 0; i--) { //get from the right
 //System.out.println(Long.toHexString(multiplier)+"\t"+Integer.toHexString((int)buffer[i]));
 value=value+(buffer[i] & 0xff)*multiplier; // add the value * the hex multiplier
 multiplier=multiplier <<8;
 }
return value;
}

A simple test case

The following code shows these examples in use, converting a Date to a byte array and back again maintaining it’s value:
long tempnow = System.currentTimeMillis();
Date tempDate= new Date(tempnow);
System.out.println("now "+tempnow);
System.out.println("Native Date "+tempDate);
        
//Convert to Byte Array and print
byte btempnow[]=longToByteArray(tempnow);
System.out.println();
System.out.print("Byte Array ");
displayByteArrayAsHex(btempnow);
        
//and Convert it back again
long converted =byteArrayToLong(btempnow);
tempDate=new Date(converted);
System.out.println("converted now "+converted);
System.out.println("converted  Date "+tempDate);

No comments:

Post a Comment