2013-10-01 23 views
0

我需要使用Java代码将Byte Array值写入Cassandra。然后,我将拥有我的C++程序,它将从Cassandra中检索字节数组数据,然后将其反序列化。如何使用字节缓冲区序列化字节数组以开始遵循Big Endian格式?

即字节数组,我将被写入到Cassandra是由三个字节数组作为现在如下─

short employeeId = 32767; 
long lastModifiedDate = "1379811105109L"; 
byte[] attributeValue = os.toByteArray(); 

所描述的,我会写employeeIdlastModifiedDateattributeValue在一起成为一个单一的字节数组和生成的字节数组我将写入Cassandra,然后我将有我的C++程序,它将从Cassandra中检索字节数组数据,然后将其反序列化以从中提取employeeId,lastModifiedDateattributeValue

我不确定在写Cassandra的时候是否应该在我的Java代码中使用Big Endian,以便在读取C++代码时可以简化C++代码?

我已经尝试了Java端,以确保它在遵循特定格式(Big Endian)的同时将所有内容写入单个字节数组,然后将该字节数组写回给Cassandra,但不确定是否这是对的还是不对?

public static void main(String[] args) throws Exception { 

    String os = "Byte Array Test"; 
    byte[] attributeValue = os.getBytes(); 

    long lastModifiedDate = 1379811105109L; 
    short employeeId = 32767; 

    ByteArrayOutputStream byteOsTest = new ByteArrayOutputStream(); 
    DataOutputStream outTest = new DataOutputStream(byteOsTest); 

    // merging everything into one Byte Array here 
    outTest.writeShort(employeeId); 
    outTest.writeLong(lastModifiedDate); 
    outTest.writeInt(attributeValue.length); 
    outTest.write(attributeValue); 

    byte[] allWrittenBytesTest = byteOsTest.toByteArray(); 

    // initially I was writing allWrittenBytesTest into Cassandra... 

    ByteBuffer bb = ByteBuffer.wrap(allWrittenBytesTest).order(ByteOrder.BIG_ENDIAN); 

    // now what value I should write into Cassandra? 
    // or does this even looks right? 

    // And now how to deserialize it? 

} 

任何人都可以帮我用这个ByteBuffer的东西吗?谢谢..

我可能会mising约字节缓冲这里微小的细节,因为这是我第一次使用它..

  1. 首先,我应该在这里使用ByteByffer都在我用例?
  2. 其次,如果是,那么在我的用例中使用它的最佳方式是什么...?

,我想要确保的是,我正在写正确成卡桑德拉按照大Endians字节顺序格式,以便于C++的一面,我没有遇到任何问题都没有,而反序列化字节的唯一的事Array ...

回答

1

首先,我从来没有使用过卡桑德拉,我只会回答关于ByteBuffer部分。

在发送字节之前,您应该先将所有内容放入字节缓冲区,否则您无法控制正在存储的内容,这正是使用ByteBuffer的要点。

要发送的字节使用:

int size = 2 + 8 + 4 + attributeValue.length; // short is 2 bytes, long 8 and int 4 

ByteBuffer bbuf = ByteBuffer.allocate(size); 
bbuf.order(ByteOrder.BIG_ENDIAN); 

bbuf.putShort(employeeId); 
bbuf.putLong(lastModifiedDate); 
bbuf.putInt(attributeValue.length); 
bbuf.put(attributeValue); 

bbuf.rewind(); 

// this is a bad approach because if you modify the returned array 
// you are directly modifying the ByteBuffer's internal array. 
byte[] bytesToStore = bbuf.array(); 

// best approach is copy the internal buffer 
byte[] bytesToStore = new byte[size]; 
bbuf.get(bytesToStore); 

您现在可以存储bytesToStore,送他们到卡桑德拉。

读他们回:

byte[] allWrittenBytesTest = magicFunctionToAcquireDataFromCassandra(); 

ByteBuffer bb = ByteBuffer.wrap(allWrittenBytesTest); 
bb.order(ByteOrder.BIG_ENDIAN); 
bb.rewind(); 

int size = allWrittenBytesTest.length - 14; 
short employeeId = bb.getShort(); 
long lastModifiedDate = bb.getLong(); 
int attributeValueLen = bb.getInt(); 
byte[] attributeValue = new byte[size]; 
bb.get(attributeValue); // read attributeValue from the remaining buffer 

你甚至都不需要存储的AttributeValue长度,因为长度可以再次确定,从allWrittenBytesTest.length减去14(即14的总和其他字段大小[2 + 4 + 8])。

编辑代码,我有一些错别字。

+0

感谢JoaoHenriques的建议...在你的例子中,你能告诉我你是如何计算大小的? )'做和可以使用它的优点是什么?感谢您的帮助.. – ferhan

+0

我已经编辑代码,以解释如何获得缓冲区的大小。字节缓冲区有一个内部字节指针,通知哪个字节读/写接下来,做回退会使指针指向零[与bbuf.position(0)相同]。每次操作都会使该指针增加操作所消耗的大小。例如,getInt()读取4个字节并增加指针通过4. putInt()也是一样,写入4个字节并将其增加4个。 –

+0

感谢您的编辑..是的,它清除了我所有的疑惑。我最后一个问题是 - 反序列化时,您没有在任何地方使用'attributeValueLen'?我们应该在某个地方使用它吗?而你错过了错误?或者它是多余的? – ferhan

1

对于字节数组endiness根本没有意义。因此,如果casandra不尝试解释您的数据,您可以使用大/小端。所以编码只对多字节值有意义。

如果你要使用不同的客户数据,并可能在不同的platfroms,我会建议采取一些协议(使用例如大端)和所有客户端使用相同的endiness。例如,Java客户端代码如下所示:

ByteBuffer bb = ByteBuffer.allocate(attributeValue.length + 14).order(ByteOrder.BIG_ENDIAN); 
    bb.putShort(employeeId); 
    bb.putLong(lastModifiedDate); 
    bb.putInt(attributeValue.length); 
    bb.put(attributeValue); 

如果您打算使用需要它的API,则必须使用ByteBuffer。例如,NIO通道与ByteBuffers协同工作,所以如果要使用SocketChannel进行连接,则可以使用ByteBuffer。 您也可以使用ByteBuffer正确格式化多字节值。例如,对于上面的代码,你可以从缓存中获取字节数组,并通过套接字发送,其中3个第一场使用大端符号包装:

sendByteArray(bb.array()); 
... 
+0

感谢barmatat您的建议..是的,这就是我还计划在您的示例使用大端...现在是什么价值我会写回卡桑德拉?我应该给卡桑德拉写'bb'吗? 14这里是什么意思? – ferhan

+0

你忘了说我没有使用Cassandra,所以不知道它们的API :(如果它接受字节数组,你可以直接从你的缓冲区中获得它并直接发送给Cassandra。14是你的第一个3字段 - short(2)+ long(8)+ int(4)。 – barmatat

3

除了手动序列化的字节缓冲区为节俭,使用本地CQL驱动程序卡桑德拉:http://github.com/datastax/java-driver

+0

你可以举个例子说明如何在Datastax中使用它吗?谢谢您的帮助。 – ferhan

+0

对我上面的问题有任何想法?谢谢 – ferhan

+0

@TechGeeky检查[这个答案](http://stackoverflow.com/questions/16870502/how-to-connect-cassandra-using-java-class/16871984#16871984)用于创建一个ks和cf并插入/阅读比较。 –

相关问题