使用GDAL/OGR操作Postgresql数据库
GDAL(Geospatial Data AbstractionLibrary)是一个在X/MIT许可协议下的开源栅格空间数据转换库。它利用抽象数据模型来表达所支持的各种文件格式。它还有一系列命令行工具来进行数据转换和处理。
本文将使用GDAL/OGR库读写Postgresql数据库中的表,代码执行环境在ubuntu12.04,
直接上代码
#include "/usr/include/gdal/ogrsf_frmts.h"
#include "/usr/include/gdal/ogr_feature.h"
#include "/usr/include/gdal/ogr_geometry.h"
#include "/usr/include/gdal/gdal_priv.h"
///////////////////////////////
//使用OGR读Postgresql
///////////////////////////////
int getFeature( vector<RoadRec>& RoadList //RoadRec是自定义数据结构
)
{
OGRRegisterAll();
const char* filepath =
"PG:dbname=test host=172.0.0.1 port=5432 user=postgres password=postgres";
const char* drivename = "PostgreSQL"; //标明是Postgresql数据库操作
const char* ptablename = "roadlist";//数据表名称 table name
OGRSFDriver* pdriver = NULL;
OGRLayer* player = NULL;
OGRDataSource* pDS = NULL;
//注册驱动,这样ogr就知道即将打开的是什么类型的文件
pdriver = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(drivename);
if ( pdriver == NULL ) {
return FAILURE;
}
//驱动注册完毕打开数据库
pDS = pdriver->Open(filepath,0);
if ( NULL == pDS ) {
return FAILURE;
}
//打开数据库中的数据表
player = pDS->GetLayerByName(ptablename);
if ( NULL == player ) {
return FAILURE;
}
//OGRFeature*相当于指向数据表中一条记录的指针,根据它可以获取每一个字段
OGRFeature* pogrfeature = NULL;
player->ResetReading();
int gid = 0;
//循环遍历每一条记录,这里的遍历是按照表中数据的存储顺序遍历
//并不会按照主键唯一值顺序遍历,这和SQL的select结果的顺序不一样
//想要一样应该创建索引,并将表数据按索引顺序存储
/*
CREATE INDEX roadlist_gid_idx
ON roadlist
USING btree
(gid);
cluster roadlist using roadlist_gid_idx;
*/
while( (pogrfeature = player->GetNextFeature()) != NULL )
{
gid++;
//获取一条记录中的几何属性字段的引用
OGRGeometry *pgeo = pogrfeature->GetGeometryRef();
if ( NULL != pgeo )
{
//判断一下是不是自己想要的类型,这里我的数据是道路,line数据
if ( wkbMultiLineString == pgeo->getGeometryType() || wkbLineString == pgeo->getGeometryType() )
{
OGRGeometry* pgeometry = pgeo;
//单独处理一下multilinestring的情况
if ( wkbMultiLineString == pgeo->getGeometryType() )
{
OGRMultiLineString* pmultilinestring = (OGRMultiLineString*)pgeo;
if( 1 != pmultilinestring->getNumGeometries() )
{
return FAILURE;
}
pgeometry = pmultilinestring->getGeometryRef(0);
}
//定义OGRLineString类型指针指向几何数据
//这样就可以使用OGRLineString提供的函数接口了
OGRLineString* pline = (OGRLineString *)pgeometry;
int pointnum = pline->getNumPoints();
RoadRec tmp;//自定义数据类型
//使用OGRFeature类提供的 GetFieldAsInteger
//方法获取每个字段的值,”link_id”,”road_name”都是字段名
tmp.link_id = pogrfeature->GetFieldAsInteger("link_id");
//tmp.src_id = pogrfeature->GetFieldAsInteger("src_id");
tmp.road_name = pogrfeature->GetFieldAsString("road_name");
tmp.one_way = pogrfeature->GetFieldAsInteger("one_way");
//获得几何属性的每一个点坐标信息
for ( int pointid = 0; pointid < pointnum;++pointid )
{
OGRPoint point;
pline->getPoint(pointid,&point);
GEO_POINT geo_point;
geo_point.x = point.getX();
geo_point.y = point.getY();
tmp.vstShplist.push_back(geo_point);
}
RoadList.push_back(tmp);
}
}
//释放Feature资源
OGRFeature::DestroyFeature(pogrfeature);
//cout<<link_id<<endl;
}
//释放指向该数据库的指针
OGRDataSource::DestroyDataSource(pDS);
return SUCCESS;
}
///////////////////////////////
//使用OGR写Postgresql
///////////////////////////////
int setFeature( const vector<RoadRec>& RoadList )
{
OGRRegisterAll();
const char* filepath =
"PG:dbname=test host=172.0.0.1 port=5432 user=postgres password=postgres";
const char* drivename = "PostgreSQL";
const char* ptablename = "roadlist";
OGRSFDriver* pdriver = NULL;
OGRLayer* player = NULL;
OGRDataSource* pDS = NULL;
pdriver = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(drivename);
if ( pdriver == NULL ) {
return FAILURE;
}
pDS = pdriver->Open(filepath,0);
if ( NULL == pDS ) {
return FAILURE;
}
//相当于sql语句中的创建数据表,只是这里只先指定表名称和几何字段属性
player = pDS->CreateLayer( ptablename,NULL,wkbLineString,NULL );
if ( NULL == player )
{
return FAILURE;
}
//定义一个字段one_way
OGRFieldDefn* pfielddefn_oneway = new OGRFieldDefn("one_way",OFTInteger);
//在数据表中创建定义的字段
player->CreateField(pfielddefn_oneway);
OGRFieldDefn* pfielddefn_name = new OGRFieldDefn("road_name",OFTString);
player->CreateField(pfielddefn_name);
//删除字段定义指针
delete pfielddefn_oneway;
delete pfielddefn_name;
int roadnum = RoadList.size();
//循环写入每一条道路数据
for ( int roadcnt = 0; roadcnt < roadnum ;++roadcnt )
{
const RoadRec& roadrec = RoadList.at(roadcnt);
OGRLineString* pline = new OGRLineString;//要写入的几何字段
int pointnum = roadrec.vstShplist.size();
for ( int pointcnt = 0; pointcnt < pointnum ;++pointcnt )
{
const GEO_POINT& point = roadrec.vstShplist.at(pointcnt);
pline->addPoint(point.x,point.y);
}
OGRGeometry* pgeo = (OGRGeometry*)pline;
pgeo->setCoordinateDimension(2);//设置坐标系维度
//创建一个指向要写入的记录的指针
//指定要写入的数据库player->GetLayerDefn()
OGRFeature* pfeature = OGRFeature::CreateFeature( player->GetLayerDefn() );
//设置当前记录的字段值
pfeature->SetField("one_way",roadrec.one_way);
pfeature->SetField("road_name",roadrec.road_name.c_str());
if ( OGRERR_NONE != pfeature->SetGeometry( pgeo ) )
{
return FAILURE;
}
//将记录写入数据表
if ( OGRERR_NONE != player->CreateFeature( pfeature ) )
{
return FAILURE;
}
delete pline;
OGRFeature::DestroyFeature(pfeature);
}
OGRDataSource::DestroyDataSource(pDS);
return SUCCESS;
}
int main()
{
vector<RoadRec> roadlist;
getFeature(roadlist);
cout<<roadlist.size()<<endl;
setFeature(roadlist);
return 0;
}
编译链接:g++ -o feature feature_pro.cpp -lgdal
转载自:https://blog.csdn.net/N_sev7/article/details/46986059