基於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】


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM