GDAL对空间数据的管理
使用GDAL可以很方便的对空间数据进行管理(这里的管理主要是指复制、移动和删除)。有人可能会说这个功能不用GDAL也能很方便的实现,其实不然。很多的空间数据不是由一个单一的文件组成,而是由一些列文件共同组成,相信大家都对Erdas的img格式比较熟悉吧,这种图像格式,对于小图像来说一般常用就只有两个,那就是img和rrd格式,如果对于一个超级大的img格式,那么一个数据可能就会有四个文件组成,后缀名分别是img、ige、rrd、rge。如果对这个数据进行复制的话,你需要写四个复制语句,同样对于矢量数据中最常用Shapfile格式,一个shp文件最少也有有三个文件组成shp、shx、dbf,常用的还有prj等其他的。对于这样的数据进行管理,还是比较繁琐的,好在GDAL中提供了相关的函数,只要一个函数,该文件所有的相关文件都会被进行管理。
下面分别对栅格数据和矢量数据进行说明。主要用到的类就是两个驱动类,GDALDirver(http://www.gdal.org/classGDALDriver.html)和 OGRSFDriver(http://www.gdal.org/ogr/classOGRSFDriver.html)。
一、栅格数据格式
1、复制数据
用到的函数是CopyFiles,函数原型是:
CPLErr GDALDriver::CopyFiles(const char *pszNewName, const char *pszOldName)参数pszNewName是复制后新栅格数据的路径,pszOldName是原始图像数据的路径。比如我要复制一个img文件【C:\Test.img】到【D:\New.img】,可以这样写:
pDriver->CopyFiles("D:\\New.img", "C:\\Test.img");执行完之后,你会发现,不但把img文件复制过去,同时还把rrd文件复制过去了。这里还有一点需要说明一下,不要以为img文件找对应的rrd是根据文件名查找的(当然这样大多数情况下是对的),其实在img文件中保存了rrd文件的路径和名称,感兴趣的同学可以看看Erdas的HFA文件格式说明。
2、移动数据
移动数据用到的函数是Rename,函数原型是:
CPLErr GDALDriver::Rename(const char *pszNewName, const char *pszOldName)
参数pszNewName是移动后新栅格数据的路径,pszOldName是原始图像数据的路径。比如我要移动一个img文件从【C:\Test.img】到【D:\New.img】,可以这样写:
pDriver->Rename("D:\\New.img", "C:\\Test.img");同上,移动后,所有的相关文件都会被移动过去。
3、删除数据
删除数据用到的函数是Delete,函数原型是:
CPLErr GDALDriver::Delete(const char * pszFilename)删除数据只有一个参数,就是要删除的图像的路径,调用该函数后,和该图像依赖的所有的文件均会被删除。
二、矢量数据格式
矢量数据中,OGR库中只提供了删除数据的函数,至于移动和拷贝暂时还没有,不过自己通过OGRDataSource实现一个也不是很难,下面就只对删除数据的接口做一个说明。
删除数据用到的函数是DeleteDataSource,函数原型是:
OGRErr OGRSFDriver::DeleteDataSource(const char * pszDataSource )参数依旧是矢量数据的路径。没什么好说的。
下面是我根据上面的函数写的几个我自己常用的函数,用来删除数据的,希望对大家有用。函数的说明以及参数都在注视里面,后面就不多说了。
头文件:
/** * @brief 判断该文件是否为图像数据 * @param strFileName 文件路径 * @return 成功返回true,否则false */ bool IsRasterFile(string strFileName); /** * @brief 判断该文件是否为矢量数据 * @param strFileName 文件路径 * @return 成功返回true,否则false */ bool IsVectorFile(string strFileName); /** * @brief 删除栅格图像 * @param pszFile 图像路径 * @return 是否删除成功,成功为RE_SUCCESS */ int RasterDelete(const char* pszFile); /** * @brief 重命名栅格图像 * @param pszOldFile 原始图像路径 * @param pszNewFile 新图像路径 * @return 是否删除成功,成功为RE_SUCCESS */ int RasterRename(const char* pszOldFile, const char* pszNewFile); /** * @brief 删除矢量数据 * @param pszFile 矢量路径 * @return 是否删除成功,成功为RE_SUCCESS */ int VectorDelete(const char* pszFile); /** * @brief 重命名矢量数据 * @param pszOldFile 原始矢量路径 * @param pszNewFile 新矢量路径 * @return 是否删除成功,成功为RE_SUCCESS */ int VectorRename(const char* pszOldFile, const char* pszNewFile);
源文件:
int RasterDelete(const char* pszFile) { path fp = pszFile; if (!exists(fp)) //文件不存在,直接返回 return RE_SUCCESS; GDALAllRegister(); //打开图像 GDALDataset *pDS = (GDALDataset *)GDALOpen(pszFile, GA_ReadOnly); if (pDS == NULL) return remove(pszFile); GDALDriver *pDriver = pDS->GetDriver(); if( pDriver == NULL ) { GDALClose((GDALDatasetH) pDS); return remove(pszFile); } GDALClose((GDALDatasetH) pDS); if(pDriver->Delete(pszFile) == CE_None) return RE_SUCCESS; else return remove(pszFile); } int RasterRename(const char* pszOldFile, const char* pszNewFile) { path fp = pszOldFile; if (!exists(fp)) //文件不存在,直接返回 return RE_FILENOTEXIST; GDALAllRegister(); //打开图像 GDALDataset *pDS = (GDALDataset *)GDALOpen(pszOldFile, GA_ReadOnly); if (pDS == NULL) return rename(pszOldFile, pszNewFile); GDALDriver *pDriver = pDS->GetDriver(); if( pDriver == NULL ) { GDALClose((GDALDatasetH) pDS); return remove(pszOldFile); } GDALClose((GDALDatasetH) pDS); if(pDriver->Rename(pszNewFile, pszOldFile) == CE_None) return RE_SUCCESS; else return rename(pszOldFile, pszNewFile); } int VectorDelete(const char* pszFile) { path fp = pszFile; if (!exists(fp)) //文件不存在,直接返回 return RE_SUCCESS; OGRRegisterAll(); //打开矢量 OGRDataSource *poDS = OGRSFDriverRegistrar::Open(pszFile, FALSE ); if( poDS == NULL ) return remove(pszFile); OGRSFDriver *poDriver = poDS->GetDriver(); if( poDriver == NULL ) { OGRDataSource::DestroyDataSource( poDS ); return remove(pszFile); } OGRDataSource::DestroyDataSource( poDS ); if(poDriver->DeleteDataSource(pszFile) == OGRERR_NONE) return RE_SUCCESS; else return remove(pszFile); } int VectorRename(const char* pszOldFile, const char* pszNewFile) { path fp = pszOldFile; if (!exists(fp)) //文件不存在,直接返回 return RE_FILENOTEXIST; OGRRegisterAll(); //打开矢量 OGRDataSource *poDS = OGRSFDriverRegistrar::Open(pszOldFile, FALSE ); if( poDS == NULL ) return rename(pszOldFile, pszNewFile); OGRSFDriver *poDriver = poDS->GetDriver(); if( poDriver == NULL ) { OGRDataSource::DestroyDataSource( poDS ); return rename(pszOldFile, pszNewFile); } OGRDataSource* poNewDS = poDriver->CopyDataSource(poDS, pszNewFile, NULL); if (poNewDS == NULL) { OGRDataSource::DestroyDataSource( poDS ); return rename(pszOldFile, pszNewFile); } OGRDataSource::DestroyDataSource( poDS ); OGRDataSource::DestroyDataSource( poNewDS ); if(poDriver->DeleteDataSource(pszOldFile) == OGRERR_NONE) return RE_SUCCESS; else return rename(pszOldFile, pszNewFile); } bool IsRasterFile(string strFileName) { string strExt = CPLGetExtension(strFileName.c_str()); to_lower(strExt); if(strExt == "rrd" || strExt == "aux"|| strExt=="ovr") return false; GDALAllRegister(); GDALDatasetH hDS = GDALOpen(strFileName.c_str(), GA_ReadOnly); if(hDS == NULL) return false; GDALClose(hDS); return true; } bool IsVectorFile(string strFileName) { string strExt = CPLGetExtension(strFileName.c_str()); to_lower(strExt); if(strExt == "dbf" || strExt == "shx") return false; OGRRegisterAll(); OGRDataSource *poDS = OGRSFDriverRegistrar::Open(strFileName.c_str(), FALSE ); if( poDS == NULL ) return false; OGRDataSource::DestroyDataSource( poDS ); return true; }这里需要说明一下,返回值的定义可以参考我之前的博客,还有就是用到了Boost库中的filesystem库和algorithm库,要不然可能编译不过去。BOOST库的头文件具体是:
#include "boost/algorithm/string.hpp" #include "boost/filesystem.hpp" using namespace boost; using namespace boost::filesystem;