继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

基于GDAL库,读取.nc文件(以海洋表温数据为例)C++版

宝慕林4294392
关注TA
已关注
手记 307
粉丝 36
获赞 149

 对于做海洋数据处理的同学,会经常遇到nc格式的文件,nc文件的格式全称是NetCDF,具体的详细解释请查询官网【https://www.unidata.ucar.edu/software/netcdf/docs/index.html】,一般从全球大洋数据库里面下载的温盐、风场及云量等数据,基本上是nc文件格式,每一个文件里面包含多个数据集,例如最简单的海面表温数据(Sea surface temperature data),数据范围是全球,空间分辨率为0.25 *0.25(~25km),时间分辨率为3 hour,所以一天的观测数据里面包含着两个子数据集(subDataset),一是海洋表温数据集,另一个是遗失数据说明信息数据集,在第一个子数据集(海洋表温数据集)内,又会包含分层数据,也就是每隔3个小时时间分辨率下的表温数据。

  基于前期查询李民录老师的《GDAL源码剖析与开发指南》一书才了解到,GDAL库本身是支持上述文件的读取的,故编译GDAL库(2.3.2版本),编译器采用MSVC2017版本,开发平台采用QT 5.11.2版本,由于QT本身不具有MSVC编译器配套的调试器,所以去微软官网下载了相应的调试器(winsdksetup.exe,安装的时候只选择安装Debugging Tools for Windows即可);经过查找GDAL官网的资料,GDAL库如若进行nc文件的读取和创建,必须还要单独下载NetCDF库文件,安装好后,配置环境变量即可,编译GDAL库时,设定好opt文件,开始编译,编译成功后即可通过下述参考博客1(Qt配置GDAL)方法,配置GDAL库。

  配置完成以后,即可进行文件的读取工作,话不多说,献上代码

读取-头文件

 

复制代码

 1 #ifndef NCFILEREAD_H  2 #define NCFILEREAD_H  3   4   5 class ncFileRead  6 {  7 public:  8     void ncFileRead::fileRead(const char *ncFileName);  9 }; 10  11 #endif // NCFILEREAD_H

复制代码

读取-源文件

复制代码

  1 #include "ncfileread.h"   2    3 #include <gdal_priv.h>   4 #include <vector>   5 #include <QVector>   6 #include <string>   7 #include <QString>   8 #include <QStringList>   9 #include <QDebug>  10   11 using namespace std;  12   13 void ncFileRead::fileRead(const char *ncFileName)  14 {  15     vector <string>         vFileSets;  16     vector <string>         pStrDesc;  17     vector<vector<float>>   allSSTPixelNum;  18   19     GDALAllRegister();  20     CPLSetConfigOption("GDAL_FILENAME_IS_UTF8","NO");//中文路径  21     GDALDataset* fileDataset = (GDALDataset*) GDALOpen(ncFileName,GA_ReadOnly);//打开HDF数据集  22     if (fileDataset == NULL)  23     {  24         return;  25     }  26   27     char** sublist = GDALGetMetadata((GDALDatasetH) fileDataset,"SUBDATASETS");//获得数据的字符串,可以打印出来看看自己需要的数据在那  28   29     int iCount = CSLCount(sublist);  30     if(iCount <= 0){  31         qDebug() << "该文件没有子数据" << endl;  32         GDALClose((GDALDriverH)fileDataset);  33     }  34   35     //存储数据集信息  36     for(int i = 0; sublist[i] != NULL;i++){  37   38         qDebug() << sublist[i] << endl;  39   40         if(i%2 != 0){  41             continue;  42         }  43   44         /**  45          * 01、海洋表温度数据集 float32  46          * 02、数据丢失补充信息 int8  47          * */  48         string tmpstr = sublist[i];  49         tmpstr = tmpstr.substr(tmpstr.find_first_of("=")+1);  50         const char *tmpc_str = tmpstr.c_str();  51   52         string tmpdsc = sublist[i+1];  53         tmpdsc = tmpdsc.substr(tmpdsc.find_first_of("=")+1);  54   55         GDALDataset* hTmpDt = (GDALDataset*)GDALOpen(tmpc_str,GA_ReadOnly);//打开该数据  56   57         if (hTmpDt != NULL)  58         {  59             vFileSets.push_back(tmpc_str);  60         }  61         if(&pStrDesc != NULL){  62             pStrDesc.push_back(tmpdsc);  63         }  64         GDALClose(hTmpDt);  65     }  66   67   68     //数据处理  69   70     qDebug() << "read RasterBand(1) ......" << endl;  71   72     //读取第一个波段  73   74     QString qtmpdsc = QString::fromStdString(pStrDesc[0]);  75     QStringList qtmpdsclist = qtmpdsc.split(" ");  76     QString dataset_name = qtmpdsclist[1];  77   78     float *lineData = NULL;  79     if (dataset_name == "sea_surface_temperature")  80     {  81         GDALDataset  *tempDt = (GDALDataset *)GDALOpen(vFileSets[0].data(), GA_ReadOnly);  82         int BandNum = tempDt->GetRasterCount();  83   84         GDALRasterBand * poBand = tempDt->GetRasterBand(1);  85         lineData = new float[1 * poBand->GetXSize()];  86         for (int iLine = 0; iLine < poBand->GetYSize(); iLine++)  87         {  88             allSSTPixelNum.resize(poBand->GetYSize());  89             for (int iPixel = 0; iPixel < poBand->GetXSize(); iPixel++)  90             {  91                 allSSTPixelNum[iLine].resize(poBand->GetXSize());  92                 poBand->RasterIO(GF_Read, 0, iLine, poBand->GetXSize(), 1,lineData, poBand->GetXSize(), 1, GDT_Float32, 0, 0);  93                 allSSTPixelNum[iLine][iPixel] = lineData[iPixel];  94              }  95         }  96         if (lineData)  97         {  98             delete[]lineData;  99             lineData = NULL; 100         } 101         GDALClose((GDALDatasetH)tempDt); 102     } 103  104  105     qDebug() << "read complete!" << endl; 106  107     GDALClose((GDALDriverH)fileDataset); 108  109 }

复制代码

主函数调用

复制代码

 1 #include <QCoreApplication>  2   3 #include "ncfileread.h"  4 #include <QWidget>  5   6 int main(int argc, char *argv[])  7 {  8     QCoreApplication a(argc, argv);  9  10     ncFileRead nfr; 11     nfr.fileRead("F:/Data File/test/SEAFLUX-OSB-CDR_V02R00_SST_D20060101_C20160824.nc"); 12  13     return a.exec(); 14 }

复制代码

 文件读取结果

https://img3.mukewang.com/5beaf95900019b6512180639.jpg

 

  至此,nc文件的读取工作已经完成,数据读取上来以后,即可进行进一步的数据处理工作。

致谢

  感谢李民录老师的指导,以及其他不知姓名的的博主,再次感谢你们对于技术的分享!

  

参考博客

1、Qt配置GDAL【https://blog.csdn.net/u010670734/article/details/53106786?locationNum=13&fps=1】

2、使用GDAL读取necdf数据【https://blog.csdn.net/bluels01/article/details/8091260】

3、使用GDAL获取HDF等数据集中的图像【https://blog.csdn.net/liminlu0314/article/details/8478339】

原文出处:https://www.cnblogs.com/thyou/p/9953845.html  

打开App,阅读手记
1人推荐
发表评论
随时随地看视频慕课网APP