4

Lazy programmer alert. :)

Cassandra stores column values as bytes (Java example). Specifying a LongType comparator compares those bytes as a long. I want the value of a long into a Cassandra-friendly byte[]. How? I poked around for awhile. I think you people can help me faster.

EDIT:

Both Alexander and Eli's answers agreed with this reverse transformation. Thanks!

Community
  • 1
  • 1
dfrankow
  • 20,191
  • 41
  • 152
  • 214

4 Answers4

5

I would write the long to a ByteArrayOutputStream wrapped in a DataOutputStream and then retrieve the raw bytes, although this will always give you your data in big endian byte order (most significant byte first):

public static byte[] getBytes(Long val)
    throws IOException
{
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    DataOutputStream dos = new DataOutputStream(baos);
    dos.writeLong(val);
    return baos.toByteArray();
}

If you want to be able to specify the endianness, you can use the ByteBuffer class:

public static byte[] getBytes(Long val)
{
    ByteBuffer buf = ByteBuffer.allocate(8);
    buf.order(ByteOrder.BIG_ENDIAN);
    buf.putLong(val);
    return buf.array();
}
Eli Courtwright
  • 186,300
  • 67
  • 213
  • 256
  • Do you know how allocating a ByteBuffer compares with just allocating the byte[] directly? I would be inclined to use byte[]-only solution because it seems cheaper. – dfrankow Apr 15 '10 at 14:52
  • I suppose I'll need to find the endianness of Cassandra. – dfrankow Apr 15 '10 at 15:22
  • @dfrankow: ByteBuffer is written in C++ and thus is probably designed for efficiency. However, my advice is to not worry about these kinds of micro-optimizations until you've profiled your code and know for sure where the inefficiencies are. Programmers are surprisingly bad at guessing where the slow spots in their code will be :) – Eli Courtwright Apr 15 '10 at 17:36
3

Here is cut and paste from java 6 DataOutputStream.writeLong

public final void writeLong(long v) throws IOException {
    writeBuffer[0] = (byte)(v >>> 56);
    writeBuffer[1] = (byte)(v >>> 48);
    writeBuffer[2] = (byte)(v >>> 40);
    writeBuffer[3] = (byte)(v >>> 32);
    writeBuffer[4] = (byte)(v >>> 24);
    writeBuffer[5] = (byte)(v >>> 16);
    writeBuffer[6] = (byte)(v >>>  8);
    writeBuffer[7] = (byte)(v >>>  0);
    out.write(writeBuffer, 0, 8);
incCount(8);
}

Here are modifications for your case

public final byte[] longToBytes(long v) {
    byte[] writeBuffer = new byte[ 8 ];

    writeBuffer[0] = (byte)(v >>> 56);
    writeBuffer[1] = (byte)(v >>> 48);
    writeBuffer[2] = (byte)(v >>> 40);
    writeBuffer[3] = (byte)(v >>> 32);
    writeBuffer[4] = (byte)(v >>> 24);
    writeBuffer[5] = (byte)(v >>> 16);
    writeBuffer[6] = (byte)(v >>>  8);
    writeBuffer[7] = (byte)(v >>>  0);

    return writeBuffer;
}
Alexander Pogrebnyak
  • 44,836
  • 10
  • 105
  • 121
2

You can crack the bytes apart by using shifts and mask, or a bit easier is ByteBuffer.wrap to wrap an 8 long byte array and using the putLong method. You must set the ByteOrder first using the ByteBuffer.order method.

President James K. Polk
  • 40,516
  • 21
  • 95
  • 125
2

You can use Cassandra's utility class: ByteBufferUtil.bytes(long n)

Michal
  • 4,846
  • 3
  • 33
  • 25