对于做海洋数据处理的同学, 会经常遇到 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 库.
配置完成以后, 即可进行文件的读取工作, 话不多说, 献上代码
读取 - 头文件
- #ifndef NCFILEREAD_H
- #define NCFILEREAD_H
- class ncFileRead
- {
- public:
- void ncFileRead::fileRead(const char *ncFileName);
- };
- #endif // NCFILEREAD_H
读取 - 源文件
- #include "ncfileread.h"
- #include <gdal_priv.h>
- #include <vector>
- #include <QVector>
- #include <string>
- #include <QString>
- #include <QStringList>
- #include <QDebug>
- using namespace std;
- void ncFileRead::fileRead(const char *ncFileName)
- {
- vector <string> vFileSets;
- vector <string> pStrDesc;
- vector<vector<float>> allSSTPixelNum;
- GDALAllRegister();
- CPLSetConfigOption("GDAL_FILENAME_IS_UTF8","NO");// 中文路径
- GDALDataset* fileDataset = (GDALDataset*) GDALOpen(ncFileName,GA_ReadOnly);// 打开 HDF 数据集
- if (fileDataset == NULL)
- {
- return;
- }
- char** sublist = GDALGetMetadata((GDALDatasetH) fileDataset,"SUBDATASETS");// 获得数据的字符串, 可以打印出来看看自己需要的数据在那
- int iCount = CSLCount(sublist);
- if(iCount <= 0){
- qDebug() <<"该文件没有子数据" << endl;
- GDALClose((GDALDriverH)fileDataset);
- }
- // 存储数据集信息
- for(int i = 0; sublist[i] != NULL;i++){
- qDebug() << sublist[i] << endl;
- if(i%2 != 0){
- continue;
- }
- /**
- * 01, 海洋表温度数据集 float32
- * 02, 数据丢失补充信息 int8
- * */
- string tmpstr = sublist[i];
- tmpstr = tmpstr.substr(tmpstr.find_first_of("=")+1);
- const char *tmpc_str = tmpstr.c_str();
- string tmpdsc = sublist[i+1];
- tmpdsc = tmpdsc.substr(tmpdsc.find_first_of("=")+1);
- GDALDataset* hTmpDt = (GDALDataset*)GDALOpen(tmpc_str,GA_ReadOnly);// 打开该数据
- if (hTmpDt != NULL)
- {
- vFileSets.push_back(tmpc_str);
- }
- if(&pStrDesc != NULL){
- pStrDesc.push_back(tmpdsc);
- }
- GDALClose(hTmpDt);
- }
- // 数据处理
- qDebug() << "read RasterBand(1) ......" << endl;
- // 读取第一个波段
- QString qtmpdsc = QString::fromStdString(pStrDesc[0]);
- QStringList qtmpdsclist = qtmpdsc.split(" ");
- QString dataset_name = qtmpdsclist[1];
- float *lineData = NULL;
- if (dataset_name == "sea_surface_temperature")
- {
- GDALDataset *tempDt = (GDALDataset *)GDALOpen(vFileSets[0].data(), GA_ReadOnly);
- int BandNum = tempDt->GetRasterCount();
- GDALRasterBand * poBand = tempDt->GetRasterBand(1);
- lineData = new float[1 * poBand->GetXSize()];
- for (int iLine = 0; iLine <poBand->GetYSize(); iLine++)
- {
- allSSTPixelNum.resize(poBand->GetYSize());
- for (int iPixel = 0; iPixel <poBand->GetXSize(); iPixel++)
- {
- allSSTPixelNum[iLine].resize(poBand->GetXSize());
- poBand->RasterIO(GF_Read, 0, iLine, poBand->GetXSize(), 1,lineData, poBand->GetXSize(), 1, GDT_Float32, 0, 0);
- allSSTPixelNum[iLine][iPixel] = lineData[iPixel];
- }
- }
- if (lineData)
- {
- delete[]lineData;
- lineData = NULL;
- }
- GDALClose((GDALDatasetH)tempDt);
- }
- qDebug() <<"read complete!" << endl;
- GDALClose((GDALDriverH)fileDataset);
- }
主函数调用
- #include <QCoreApplication>
- #include "ncfileread.h"
- #include <QWidget>
- int main(int argc, char *argv[])
- {
- QCoreApplication a(argc, argv);
- ncFileRead nfr;
- nfr.fileRead("F:/Data File/test/SEAFLUX-OSB-CDR_V02R00_SST_D20060101_C20160824.nc");
- return a.exec();
- }
文件读取结果
至此, 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