2014-02-04 5 views
2

Я пытаюсь использовать ByteBuffer правильно с BigEndian формат порядка байтов ..Как избежать исключения BufferOverflow?

У меня есть несколько полей, которые я пытаюсь собрать в одну ByteBuffer перед сохранением в базе данных Cassandra.

Это массив байт, который я буду писать в Cassandra состоит из трех байтовых массивов, как описано

ценам ниже
short employeeId = 32767; 
long lastModifiedDate = "1379811105109L"; 
byte[] attributeValue = os.toByteArray(); 

Теперь мне нужно живо сжимать данные AttributeValue перед сохранением в Кассандре -

employeeId (do not snappy compressed) 
lastModifiedDate (do not snappy compressed) 
attributeValue (snappy compressed it) 

Теперь я буду писать employeeId, lastModifiedDate и мгновенным сжатый attributeValue в единый массив байтов, и что в результате байтовый массив Я пишу в Кассандре и тогда у меня будет мой C++ программа, которая будет извлекать данные байт-массива из Cassandra, а затем десериализует ее для извлечения employeeId, lastModifiedDate и распакует этот attributeValue, используя snappy из него.

Чтобы сделать это, я использую ByteBuffer с форматом байтового байта BigEndian.

Я поставил этот код вместе -

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

     String text = "Byte Buffer Test"; 
     byte[] attributeValue = text.getBytes(); 

     long lastModifiedDate = 1289811105109L; 
     short employeeId = 32767; 

     // snappy compressing it and this line gives BufferOverflowException 
     byte[] compressed = Snappy.compress(attributeValue); 

     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(compressed); // storing the snappy compressed data 

     bbuf.rewind(); 

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

     // write bytesToStore in Cassandra... 

     // Now retrieve the Byte Array data from Cassandra and deserialize it... 
     byte[] allWrittenBytesTest = bytesToStore;//magicFunctionToRetrieveDataFromCassandra(); 

     // I am not sure whether the below read code will work fine or not.. 
     ByteBuffer bb = ByteBuffer.wrap(allWrittenBytesTest); 

     bb.order(ByteOrder.BIG_ENDIAN); 
     bb.rewind(); 

     short extractEmployeeId = bb.getShort(); 
     long extractLastModifiedDate = bb.getLong(); 
     int extractAttributeValueLength = bb.getInt(); 
     byte[] extractAttributeValue = new byte[extractAttributeValueLength]; 

     bb.get(extractAttributeValue); // read attributeValue from the remaining buffer 

     System.out.println(extractEmployeeId); 
     System.out.println(extractLastModifiedDate); 
     System.out.println(new String(Snappy.uncompress(extractAttributeValue))); 

} 

Как-то выше код бросает BufferOverflowException -

Exception in thread "main" java.nio.BufferOverflowException 
    at java.nio.HeapByteBuffer.put(HeapByteBuffer.java:165) 
    at java.nio.ByteBuffer.put(ByteBuffer.java:813) 

Почему я мгновенным сжатия данных перед сохранением в Кассандре, потому что, когда я получить данные из Cassandra из C++-кода, тогда он должен быть сжатым, поэтому на нашей C++-карте потребуется меньше места. И мы разложим его только тогда, когда люди обратятся к нам.

Может кто-нибудь взглянуть и сообщить мне, что я здесь делаю неправильно? И как я должен читать данные тогда?

+1

Вы не правильно вычисляете 'размер'. Вы действительно не могли понять это из-за исключения? – kdgregory

+0

Но он бросает исключение, сжимая его 'Snappy.compress (attributeValue);'? – AKIWEB

+0

Вряд ли. Вы видите «Snappy» в любом месте трассировки стека? – kdgregory

ответ

1

При назначении оригинального ByteBuffer вы должны использовать длину compressed.

Смежные вопросы