2009-09-23 5 views
16

Я ищу «эквивалент» C++ Java ByteBuffer.C++ эквивалент Java ByteBuffer?

Возможно, мне не хватает очевидного или просто нужно использовать изолированный пример использования, чтобы уточнить. Я просмотрел семейство iostream & похоже, что он может служить основой. В частности, я хочу иметь возможность:

  • построить буфер из массива/точки байта и получить примитивы из буфера, например. getByte, getInt
  • создать буфер с использованием примитивов, например. putByte, putInt, а затем получить байтовый массив/указатель.
+0

Важно отметить, что в 'получить (T) и' положим (T), 'T' * не *' byte'. Это * другие * примитивные типы, такие как 'int',' float' и 'short'. –

+0

Да, это был неудачный выбор именования с моей стороны. Я сделал это яснее. – hplbsh

ответ

14

Вы stringbuf, filebuf или вы могли бы использовать vector<char>.


Это простой пример использования stringbuf:

std::stringbuf buf; 
char data[] = {0, 1, 2, 3, 4, 5}; 
char tempbuf[sizeof data]; 

buf.sputn(data, sizeof data); // put data 
buf.sgetn(tempbuf, sizeof data); // get data 

Благодаря @Pete Kirkham для идеи родовых функций.

#include <sstream> 

template <class Type> 
std::stringbuf& put(std::stringbuf& buf, const Type& var) 
{ 
    buf.sputn(reinterpret_cast<const char*>(&var), sizeof var); 

    return buf; 
} 

template <class Type> 
std::stringbuf& get(std::stringbuf& buf, Type& var) 
{ 
    buf.sgetn(reinterpret_cast<char*>(&var), sizeof(var)); 

    return buf; 
} 

int main() 
{ 
    std::stringbuf mybuf; 
    char byte = 0; 
    int var; 

    put(mybuf, byte++); 
    put(mybuf, byte++); 
    put(mybuf, byte++); 
    put(mybuf, byte++); 

    get(mybuf, var); 
} 
+1

Это был бы лучший пример, если бы предмет, извлеченный из буфера, не был другим массивом символов. 'ByteBuffer' позволяет извлекать * другие * примитивные типы из байтового буфера, а не только байты. http://java.sun.com/j2se/1.4.2/docs/api/java/nio/ByteBuffer.html –

+0

Мой выбор get (T) и put (T) в качестве примеров был довольно низким; Я хотел бы извлечь переменные из буфера. std :: stringbuf чувствует себя в правильном направлении. Благодарю. – hplbsh

+0

Его несимметричный характер. Возможно, std :: streambuf - лучший выбор в этом случае, хотя оба они должны быть работоспособными. – hplbsh

3
std::vector<char> bytes; 

bytes.push_back(some_val); // put 

char x = bytes[N];   // get 

const char* ptr = &bytes[0]; // pointer to array 
0

для станд :: вектор более эффективным является метод

push_back(T) 

Вы можете найти больше здесь:

http://www.cppreference.com/wiki/stl/vector/start

и вообще о CPP СТЛ LIBS

http://www.cppreference.com/wiki/stl/start

Есть много контейнеров, зависит от того, что вам это нужно для агрегации скорости

  • (возможности быстрого написания) или
  • быстрого чтения

посмотри на станде :: list, std :: vector.

8

stringstream предоставляет основные неформатированные get и write операции по созданию блоков символов. Специализировать по T либо подклассу, либо обернуть ее, либо предоставить бесплатные постоянные функции шаблонов для использования памяти для получения/записи соответствующего размера.

template <typename T> 
std::stringstream& put (std::stringstream& str, const T& value) 
{ 
    union coercion { T value; char data[ sizeof (T) ]; }; 

    coercion c; 

    c.value = value; 

    str.write (c.data, sizeof (T)); 

    return str; 
} 

template <typename T> 
std::stringstream& get (std::stringstream& str, T& value) 
{ 
    union coercion { T value; char data[ sizeof (T) ]; }; 

    coercion c; 

    c.value = value; 

    str.read (c.data, sizeof (T)); 

    value = c.value; 

    return str; 
} 

Вы могли бы написать такие шаблоны для любой другой поток или вектор вы хотите - в случае вектора, он должен был бы использовать вставку, а не писать.

+0

Хорошее решение :) Я думаю, что потоки - это больше инструмент для чтения и записи * форматированных данных *. Почему я должен использовать поток как буфер, где внутри потока есть буфер. Тем не менее, я думаю, что ваши общие функции - отличная идея. – AraK

+0

Я предпочитаю потоки, так как мне нравится принуждение к bool и идиома возврата потока для цепочки, а не возврат буфера количества байтов, написанных и вынужденных обсуждать это тестирование. –

1

Спасибо за все входные, это привело к этому довольно простое решение:


class ByteBuffer : std::stringbuf 
{ 
public: 
    template 
    size_t get(T &out) 
    { 
     union coercion { T value; char data[ sizeof (T) ]; }; 

     coercion c; 

     size_t s= xsgetn(c.data, sizeof(T)); 

     out= c.value; 

     return s; 
    } 

    template 
    size_t put(T &in) 
    { 
     union coercion { T value; char data[ sizeof (T) ]; }; 

     coercion c; 

     c.value= in; 

     return xsputn(c.data, sizeof(T)); 
    } 

    size_t get(uint8_t *out, size_t count) 
    { 
     return xsgetn((char *)out, count); 
    } 

    size_t put(uint8_t *out, size_t count) 
    { 
     return xsputn((char *)out, count); 
    } 
}; 

Для использования, например:


void ByteBufferTest(void) 
{ 
    ByteBuffer bb; 

    float f= 4; 
    uint8_t u8= 1; 
    uint16_t u16= 2; 
    uint32_t u32= 4; 
    uint64_t u64= 8; 

    bb.put(f); 
    bb.put(u8); 
    bb.put(u16); 
    bb.put(u32); 
    bb.put(u64); 

    uint8_t array[19]; 

    bb.get(array, 19); 

    // or 

    bb.get(f); 
    bb.get(u8); 
    bb.get(u16); 
    bb.get(u32); 
    bb.get(u64); 
} 
+1

-1: Мне очень не нравится идея, что вы подклассифицируете std :: stringbuf. Вместо этого используйте композицию. Большинство типов в этом пространстве имен не предназначены для этого. Кроме того, почему вы используете size_t? – Arafangion

4

я написал некоторое время назад, чтобы делать то, что вы просите для. Дайте ему шанс:

https://code.google.com/p/bytebuffer-cpp/

+0

Это не похоже на различие порядка байтов для интегральных типов, если писатель и читатель работают на разных архитектурах. Я думаю, что ByteBuffer от Java по умолчанию большой по умолчанию, но дает возможность изменять порядок байтов. Любые альтернативы? – Hoobajoob

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