Я пытаюсь использовать 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++-карте потребуется меньше места. И мы разложим его только тогда, когда люди обратятся к нам.
Может кто-нибудь взглянуть и сообщить мне, что я здесь делаю неправильно? И как я должен читать данные тогда?
Вы не правильно вычисляете 'размер'. Вы действительно не могли понять это из-за исключения? – kdgregory
Но он бросает исключение, сжимая его 'Snappy.compress (attributeValue);'? – AKIWEB
Вряд ли. Вы видите «Snappy» в любом месте трассировки стека? – kdgregory