在 Redis 中存储字符向量 - 包含 NUL
Storing vector of chars in Redis - containing NUL
我想将 JPEG 图像作为单个键值对存储在 Redis 中。
从 OpenCV,我从 imencode()
得到一个 std::vector<unsigned char> jpeg
现在,我使用 Hiredis 将此向量转换为 std::string
和 SET
。
问题是 jpeg
向量包含 NUL
个字符 (ANSII == 0
) 而 Hiredis SET
函数接收 value.c_str()
。 .c_str()
在 NUL
第一次出现后截断字符串,因此只有这个子字符串存储在数据库中。
我的问题是:如何使用 Hiredis SET
和 GET
一个 std::vector<unsigned char>
(包含 NUL
)? (最小化运行时间至关重要。)
这是我的代码:
// 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;
}
在展示代码之前,我想再警告一次,如果没有适当的序列化,存储二进制数据可能会出现问题。至少要确保你所有的服务器都是相同的字节顺序并且有相同的 sizeof(int).
std::vector<char> v{'A', 'B', '[=10=]', '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 );
并阅读 python。
>>> import redis
>>> r = redis.StrictRedis(host='localhost', port=6379, db=0)
>>> r.get("jpeg")
'AB\x00CD'
我想将 JPEG 图像作为单个键值对存储在 Redis 中。
从 OpenCV,我从 imencode()
std::vector<unsigned char> jpeg
现在,我使用 Hiredis 将此向量转换为 std::string
和 SET
。
问题是 jpeg
向量包含 NUL
个字符 (ANSII == 0
) 而 Hiredis SET
函数接收 value.c_str()
。 .c_str()
在 NUL
第一次出现后截断字符串,因此只有这个子字符串存储在数据库中。
我的问题是:如何使用 Hiredis SET
和 GET
一个 std::vector<unsigned char>
(包含 NUL
)? (最小化运行时间至关重要。)
这是我的代码:
// 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;
}
在展示代码之前,我想再警告一次,如果没有适当的序列化,存储二进制数据可能会出现问题。至少要确保你所有的服务器都是相同的字节顺序并且有相同的 sizeof(int).
std::vector<char> v{'A', 'B', '[=10=]', '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 );
并阅读 python。
>>> import redis
>>> r = redis.StrictRedis(host='localhost', port=6379, db=0)
>>> r.get("jpeg")
'AB\x00CD'