C++访问Redis的mset 二进制数据接口封装方案
需求 C++中使用hiredis客户端接口访问redis; 以下给出三种封装实现方案; 简单拼接方案 在redis-cli中,mset的语法是这样的: 复制代码 代码如下: /opt/colin$./redis-cli mset a 11 b 22 c 333 OK 按照这样的语法拼接后,直接使用hiredis字符串接口redisCommand传递: void msetNotBinary(redisContext *c,const vector<string> &vtKey,const vector<string> & vtVal ) { if(vtKey.size() != vtVal.size()) { throw runtime_error( "Redis error" ); } string strCmd = "MSET"; for(int i = 0; i < vtKey.size(); i++) { strCmd += " "+vtKey[i]+" "+vtVal[i]; } cout << "strCmd:" << strCmd << endl; void * r = redisCommand(c,strCmd.c_str() ); if ( !r ) throw runtime_error( "Redis error" ); freeReplyObject( r ); } void do_test( redisContext *c ) { vector<string> vtKey; vector<string> vtVal; vtKey.push_back("A"); vtVal.push_back("AAAA"); vtKey.push_back("B"); vtVal.push_back("BBBB"); vtKey.push_back("C"); vtVal.push_back("CCCC"); //add a binary data vtKey.push_back("D"); vtVal.push_back(""); char a[] = "ABCDE"; a[2] = 0; vtVal[3].assign(a,5); try { msetNotBinary(c,vtKey,vtVal ); //mset1( c,vtVal ); //mset2( c,vtVal ); } catch ( runtime_error & ) { cout << "Error" << endl; } } int main(int argc,char *argv[]) { redisContext *c; c = redisConnect("127.0.0.1",6379); if (c->err) { cout << "Connection error: " << c->errstr << endl; return -1; } do_test(c); redisFree(c); return 0; } 这种方式可以处理mset多个字符串数据,但对于数据内容为二进制数据的无能为力; redisCommandArgv接口传递 方案 对于多个参数传递,hiredis提供了以下接口,这个接口中最后一个参数是所有的传入数据的内容长度, void *redisCommandArgv(redisContext *c,int argc,const char **argv,const size_t *argvlen); void mset1( redisContext *c,const vector<string> & vtVal ) { if(vtKey.size() != vtVal.size()) { throw runtime_error( "Redis error" ); } char ** argv = new char*[vtKey.size() + vtVal.size() + 1 ]; size_t * argvlen = new size_t[vtKey.size() + vtVal.size() + 1 ]; int j = 0; argv[j] = new char[5]; memcpy(argv[j],"MSET",4); argvlen[j] = 4; ++j; for(int i = 0 ; i < vtKey.size();i++) { argvlen[j] = vtKey[i].length(); argv[j] = new char[argvlen[j]]; memset((void*)argv[j],argvlen[j] ); memcpy((void*)argv[j],vtKey[i].data(),vtKey[i].length()); j++; argvlen[j] = vtVal[i].length(); argv[j] = new char[argvlen[j]]; memset((void*)argv[j],argvlen[j]); memcpy((void*)argv[j],vtVal[i].data(),vtVal[i].length()); j++; } //if not use const_cast<const char**>,compile error //for why assign from char** to const char** error,see my blog ... void *r = redisCommandArgv(c,vtKey.size() + vtVal.size() + 1,const_cast<const char**>(argv),argvlen ); if ( !r ) throw runtime_error( "Redis error" ); freeReplyObject( r ); for(int i = 0;i < vtKey.size();i++) { delete [] argv[i]; argv[i] = NULL; } delete []argv; delete []argvlen; argv = NULL; } redisCommandArgv接口传递的Vector方案 还是使用redisCommandArgv接口,使用vector来构造这个const char **,这个方法是从参考资料1中学到的: void mset2( redisContext *c,const vector<string> & vtVal) { if(vtKey.size() != vtVal.size()) { throw runtime_error( "Redis error" ); } vector<const char *> argv( vtKey.size() + vtVal.size() + 1 ); vector<size_t> argvlen( vtKey.size() + vtVal.size() + 1 ); int j = 0; static char msetcmd[] = "MSET"; argv[j] = msetcmd; argvlen[j] = sizeof(msetcmd)-1; ++j; for(int i = 0;i< vtKey.size();++i) { argvlen[j] = vtKey[i].length(); argv[j] = new char[argvlen[j]]; memset((void*)argv[j],vtVal[i].length()); j++; } void *r = redisCommandArgv(c,argv.size(),&(argv[0]),&(argvlen[0]) ); if ( !r ) throw runtime_error( "Redis error" ); freeReplyObject( r ); } 这样,就实现二进制数据的传递; 二进制校验 程序执行后,可以用redis-cli来验证: 对于非二进制安全的实现,二进制内容是截断的: 复制代码 代码如下: /opt/app/colin$./redis-cli get D "AB" 而二进制安全的实现接口,二进制数据的0通过转义方式显示: 复制代码 代码如下: /opt/app/colin$./redis-cli get D "ABx00DE" 完整可执行的代码详见github:https://github.com/me115/cppset/tree/master/2DimArray 以上所述就是本文的全部内容了,希望大家能够喜欢。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- ruby-on-rails – 如何将数组传递给Rails中的fields_for?
- wpf – 依赖属性SetValue()和SetCurrentValue()之间的区别是
- AJAX
- ruby-on-rails – 我似乎无法在一个普通的字符串上工作
- JSON.stringify的参数
- flex4页面中如何保持选中titlewindow在最上层。
- SST25 SPI_TO_FLASH
- c# – Input.GetMouseButtonUp不可靠. (统一)
- ruby-on-rails – 在ActiveRecord Create上验证Carrierwave
- C#循环遍历所有MDI childer并关闭除当前之外的所有其他形式