zoukankan      html  css  js  c++  java
  • 基于GDAL库,读取.nc文件(以海洋表温数据为例)C++版

      对于做海洋数据处理的同学,会经常遇到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 }

     文件读取结果

      至此,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】

  • 相关阅读:
    真正的e时代
    在线手册
    UVA 10616 Divisible Group Sums
    UVA 10721 Bar Codes
    UVA 10205 Stack 'em Up
    UVA 10247 Complete Tree Labeling
    UVA 10081 Tight Words
    UVA 11125 Arrange Some Marbles
    UVA 10128 Queue
    UVA 10912 Simple Minded Hashing
  • 原文地址:https://www.cnblogs.com/thyou/p/9953845.html
Copyright © 2011-2022 走看看