使用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;elsereturn 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;elsereturn 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;elsereturn 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;elsereturn 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;