基于GDAL库,读取.nc文件

  对于做海洋数据处理的同学,会经常遇到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. 1 #ifndef NCFILEREAD_H
  2. 2 #define NCFILEREAD_H
  3. 3
  4. 4
  5. 5 class ncFileRead
  6. 6 {
  7. 7 public:
  8. 8 void ncFileRead::fileRead(const char *ncFileName);
  9. 9 };
  10. 10
  11. 11 #endif // NCFILEREAD_H

读取-源文件

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

主函数调用

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

版权声明:本文为thyou原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/thyou/p/9953845.html