Хранение вектора символов в Redis — содержащем NUL

Я хочу сохранить изображение JPEG в Redis как одну пару ключ-значение.
Из OpenCV я получаю std::vector<unsigned char> jpeg от imencode()

Теперь я конвертирую этот вектор в std::string а также SET это с Hiredis.
Проблема в том, что jpeg вектор содержит NUL персонажи (ANSII == 0) и Hiredis SET функция получает value.c_str(), .c_str() обрезает строку после первого появления NULи, следовательно, только эта подстрока хранится в БД.

Мой вопрос: как я могу SET а также GET std::vector<unsigned char> (содержащий NUL) с Hiredis? (Минимизация времени выполнения имеет решающее значение.)

Вот мой код:

// Create vector of uchars, = From CV [Disregard inefficiency here]

std::vector<unsigned char> jpeg;
jpeg.push_back( 'a' );
jpeg.push_back( 'b' );
jpeg.push_back( (unsigned char) 0 );
jpeg.push_back( 'c' );
jpeg.push_back( 'd' );

// Convert to string

std::string word = "";
for (int i=0; i<jpeg.size(); ++i)
{
word.push_back(jpeg[i]);
}

std::cout << "word = " << word << std::endl;
std::cout << "word.c_str() = " << word.c_str() << std::endl;

// connect redis

std::string hostname = "127.0.0.1";
int port = 6379;
timeval timeout = { 1, 500000 }; // 1.5 seconds
redisContext* context = redisConnectWithTimeout(hostname.c_str(), port, timeout);

// set redis

std::string key = "jpeg";
redisReply* reply = (redisReply *)redisCommand(context, "SET %s %s", key.c_str(), word.c_str() );
freeReplyObject( (void*) reply);

// get redis

reply = (redisReply *)redisCommand(context, "GET %s", key.c_str() );
std::string value = reply->str;
freeReplyObject((void*) reply);
std::cout << "returned value = " << value << std::endl;

// Convert back to vector of uchars (this should be the same as the original jpeg)  [Disregard inefficiency here]

std::vector<unsigned char> jpeg_returned;
for (int i=0; i<value.size(); ++i)
{
jpeg_returned.push_back(value[i]);
// std::cout << "value[i] = " << value[i] << std::endl;
}

1

Решение

Прежде чем показывать код, я хочу еще раз предупредить, что хранение двоичных данных без надлежащей сериализации может быть проблематичным. По крайней мере, убедитесь, что все ваши серверы имеют одинаковый порядок байтов и имеют одинаковый размер (int).

std::vector<char> v{'A', 'B', '\0', 'C', 'D'};

std::string key = "jpeg";
redisReply* reply = static_cast<redisReply *>( redisCommand(context, "SET %s %b", key.c_str(), v.data(), v.size() ) );
freeReplyObject( reply );

И чтение из питона.

>>> import redis
>>> r = redis.StrictRedis(host='localhost', port=6379, db=0)
>>> r.get("jpeg")
'AB\x00CD'
1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]