背景:
现项目需要使用c++连接hbase,但是网上资料参差不齐,没有完整的连接项目。通过自己整理与查阅资料,现整理步骤如下(windows环境):
1、下载thrift,并配置环境变量
2、用Thrift 生成访问Hbase所需的C++文件
注意:使用thrift连接hbase有两种方式,分别对应thrift与thrift2(.thrift文件在hbase源码文件夹中,路径如下图)
将.thrift文件放置到文件夹,进入cmd输入命令: thrift --gen cpp XXX.thrift 就会形成如下c文件
注意:获取连接hbase的c文件另一种方式是编译hbase源码,c文件所在路径如下图
3、新建QT或者其它c++项目,在工作区间导入编译好的thrift,boost。
①工程目录(QT)
②工程工作区间
划横线的部分是事先编译好的boost与thrift,随便下载源文件百度一下编译过程,本文不赘述。
4、编写连接demo
#include <QCoreApplication>
#include <iostream>
#include <boost/lexical_cast.hpp>
#include <thrift/protocol/TBinaryProtocol.h>
#include <thrift/transport/TSocket.h>
#include <thrift/transport/TTransportUtils.h>
#include "Hbase.h"
using namespace apache::thrift;
using namespace apache::thrift::protocol;
using namespace apache::thrift::transport;
using namespace apache::hadoop::hbase::thrift;
namespace {
typedef std::vector<std::string> StrVec;
typedef std::map<std::string,std::string> StrMap;
typedef std::vector<ColumnDescriptor> ColVec;
typedef std::map<std::string,ColumnDescriptor> ColMap;
typedef std::vector<TCell> CellVec;
typedef std::map<std::string,TCell> CellMap;
static void
printRow(const std::vector<TRowResult> &rowResult)
{
for (size_t i = 0; i < rowResult.size(); i++) {
std::cout << "row: " << rowResult[i].row << ", cols: ";
for (CellMap::const_iterator it = rowResult[i].columns.begin();
it != rowResult[i].columns.end(); ++it) {
std::cout << it->first << " => " << it->second.value << "; ";
}
std::cout << std::endl;
}
}
static void
printVersions(const std::string &row, const CellVec &versions)
{
std::cout << "row: " << row << ", values: ";
for (CellVec::const_iterator it = versions.begin(); it != versions.end(); ++it) {
std::cout << (*it).value << "; ";
}
std::cout << std::endl;
}
}
int
main(int argc, char** argv)
{
// if (argc < 3) {
// std::cerr << "Invalid arguments!\n" << "Usage: DemoClient host port" << std::endl;
// return -1;
// }
QCoreApplication a(argc, argv);
bool isFramed = false;
// std::shared_ptr<TTransport> socket(new TSocket(argv[1], boost::lexical_cast<int>(argv[2])));
//连接IP,端口号
std::shared_ptr<TTransport> socket(new TSocket("XXX.XXX.XXX.XXX", 9090));
std::shared_ptr<TTransport> transport;
if (isFramed) {
transport.reset(new TFramedTransport(socket));
} else {
transport.reset(new TBufferedTransport(socket));
}
std::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));
const std::map<Text, Text> dummyAttributes; // see HBASE-6806 HBASE-4658
HbaseClient client(protocol);
try {
transport->open();
std::string t("C002");
//-------------------------------------------------------------------------------------
//
// Scan all tables, look for the demo table and delete it.
//
// std::cout << "scanning tables..." << std::endl;
// StrVec tables;
// client.getTableNames(tables);
// for (StrVec::const_iterator it = tables.begin(); it != tables.end(); ++it) {
// std::cout << " found: " << *it << std::endl;
// if (t == *it) {
// if (client.isTableEnabled(*it)) {
// std::cout << " disabling table: " << *it << std::endl;
// client.disableTable(*it);
// }
// std::cout << " deleting table: " << *it << std::endl;
// client.deleteTable(*it);
// }
// }
//-------------------------------------------------------------------------------------
//
// Create the demo table with two column families, entry: and unused:
//
ColVec columns;
columns.push_back(ColumnDescriptor());
columns.back().name = "entry:";
columns.back().maxVersions = 10;//版本保留
columns.push_back(ColumnDescriptor());
columns.back().name = "unused:";
std::cout << "creating table: " << t << std::endl;
try {
client.createTable(t, columns);
} catch (const AlreadyExists &ae) {
std::cerr << "WARN: " << ae.message << std::endl;
}
// // 获取表格列族
ColMap columnMap;
// client.getColumnDescriptors(columnMap, t);
// std::cout << "column families in " << t << ": " << std::endl;
// for (ColMap::const_iterator it = columnMap.begin(); it != columnMap.end(); ++it) {
// std::cout << " column: " << it->second.name << ", maxVer: " << it->second.maxVersions << std::endl;
// }
// //
// // Test UTF-8 handling
// //
// std::string invalid("foo-\xfc\xa1\xa1\xa1\xa1\xa1");
// std::string valid("foo-\xE7\x94\x9F\xE3\x83\x93\xE3\x83\xBC\xE3\x83\xAB");
// // non-utf8 is fine for data
std::vector<Mutation> mutations;
// mutations.push_back(Mutation());
// mutations.back().column = "entry:foo";
// mutations.back().value = invalid;
// client.mutateRow(t, "foo", mutations, dummyAttributes);
// // try empty strings
// mutations.clear();
// mutations.push_back(Mutation());
// mutations.back().column = "entry:";
// mutations.back().value = "";
// client.mutateRow(t, "", mutations, dummyAttributes);
// // this row name is valid utf8
// mutations.clear();
// mutations.push_back(Mutation());
// mutations.back().column = "entry:foo";
// mutations.back().value = valid;
// client.mutateRow(t, valid, mutations, dummyAttributes);
// // non-utf8 is now allowed in row names because HBase stores values as binary
// mutations.clear();
// mutations.push_back(Mutation());
// mutations.back().column = "entry:foo";
// mutations.back().value = invalid;
// client.mutateRow(t, invalid, mutations, dummyAttributes);
// // Run a scanner on the rows we just created
StrVec columnNames;
columnNames.push_back("entry:");
// //扫描表格每行的值
// std::cout << "Starting scanner..." << std::endl;
int scanner = client.scannerOpen(t, "", columnNames, dummyAttributes);
// try {
// while (true) {
// std::vector<TRowResult> value;
// client.scannerGet(value, scanner);
// if (value.size() == 0)
// break;
// printRow(value);
// }
// } catch (const IOError &ioe) {
// std::cerr << "FATAL: Scanner raised IOError" << std::endl;
// }
// //关闭扫描
// client.scannerClose(scanner);
// std::cout << "Scanner finished" << std::endl;
//-------------------------------------------------------------------------------------
// Run some operations on a bunch of rows.
for (int i = 100; i >= 0; --i) {
// format row keys as "00000" to "00100"
char buf[32];
sprintf(buf, "%05d", i);
std::string row(buf);
std::vector<TRowResult> rowResult;
mutations.clear();
mutations.push_back(Mutation());
mutations.back().column = "unused:";
mutations.back().value = "DELETE_ME";
client.mutateRow(t, row, mutations, dummyAttributes);
client.getRow(rowResult, t, row, dummyAttributes);
printRow(rowResult);
//删除行
//client.deleteAllRow(t, row, dummyAttributes);
mutations.clear();
mutations.push_back(Mutation());
mutations.back().column = "entry:num";
mutations.back().value = "0";
mutations.push_back(Mutation());
mutations.back().column = "entry:foo";
mutations.back().value = "FOO";
client.mutateRow(t, row, mutations, dummyAttributes);
client.getRow(rowResult, t, row, dummyAttributes);
printRow(rowResult);
// sleep to force later timestamp
//poll(0, 0, 50);
mutations.clear();
mutations.push_back(Mutation());
mutations.back().column = "entry:foo";
mutations.back().isDelete = true;
mutations.push_back(Mutation());
mutations.back().column = "entry:num";
mutations.back().value = "-1";
client.mutateRow(t, row, mutations, dummyAttributes);
client.getRow(rowResult, t, row, dummyAttributes);
printRow(rowResult);
mutations.clear();
mutations.push_back(Mutation());
mutations.back().column = "entry:num";
mutations.back().value = boost::lexical_cast<std::string>(i);
mutations.push_back(Mutation());
mutations.back().column = "entry:sqr";
mutations.back().value = boost::lexical_cast<std::string>(i*i);
client.mutateRow(t, row, mutations, dummyAttributes);
client.getRow(rowResult, t, row, dummyAttributes);
printRow(rowResult);
mutations.clear();
mutations.push_back(Mutation());
mutations.back().column = "entry:num";
mutations.back().value = "-999";
mutations.push_back(Mutation());
mutations.back().column = "entry:sqr";
mutations.back().isDelete = true;
client.mutateRowTs(t, row, mutations, 1, dummyAttributes); // shouldn't override latest
client.getRow(rowResult, t, row, dummyAttributes);
printRow(rowResult);
CellVec versions;
client.getVer(versions, t, row, "entry:num", 10, dummyAttributes);
printVersions(row, versions);
assert(versions.size());
std::cout << std::endl;
try {
std::vector<TCell> value;
client.get(value, t, row, "entry:foo", dummyAttributes);
if (value.size()) {
std::cerr << "FATAL: shouldn't get here!" << std::endl;
return -1;
}
} catch (const IOError &ioe) {
// blank
}
}
// scan all rows/columns
columnNames.clear();
client.getColumnDescriptors(columnMap, t);
std::cout << "The number of columns: " << columnMap.size() << std::endl;
for (ColMap::const_iterator it = columnMap.begin(); it != columnMap.end(); ++it) {
std::cout << " column with name: " + it->second.name << std::endl;
columnNames.push_back(it->second.name);
}
std::cout << std::endl;
std::cout << "Starting scanner..." << std::endl;
scanner = client.scannerOpenWithStop(t, "00020", "00040", columnNames, dummyAttributes);
try {
while (true) {
std::vector<TRowResult> value;
client.scannerGet(value, scanner);
if (value.size() == 0)
break;
printRow(value);
}
} catch (const IOError &ioe) {
std::cerr << "FATAL: Scanner raised IOError" << std::endl;
}
client.scannerClose(scanner);
std::cout << "Scanner finished" << std::endl;
transport->close();
} catch (const TException &tx) {
std::cerr << "ERROR: " << tx.what() << std::endl;
}
return a.exec();
}
5、运行项目,查看操作结果。
项目运行
hbase数据库查看