title: 解码已加载的 GRIB 消息

weight: 3

目标尽可能地少解码。永远不要解码整个已加载的 GRIB 消息。可以使用 grib_dump -D <grib_file> 查看到底有多少个 ecCodes key。

用于解码的主要函数:

  1. int codes_get_long (codes_handle *h, const char *key, long *value);
  2. int codes_get_double (codes_handle *h, const char *key, double *value)
  3. int codes_get_string (codes_handle *h, const char *key, char *mesg, size_t *length)
  4. int codes_get_long_array (codes_handle *h, const char *key, long *vals, size_t *length)
  5. int codes_get_double_array (codes_handle *h, const char *key, double *vals, size_t *length)

帮助函数

获取一个(数组)数据的大小:

  1. int codes_get_size(codes_handle* h, const char* key,size_t *size);
  2. int grib_get_size(grib_handle* h, const char* key,size_t *size);

详细输出 grib 消息的内容:

  1. void codes_dump_content(codes_handle* h,FILE* out,const char* mode, unsigned long option_flags,void* arg);
  2. void grib_dump_content(grib_handle* h,FILE* out,const char* mode, unsigned long option_flags,void* arg);

检查某个 key 是否被定义(存在):

  1. int codes_is_defined(codes_handle* h, const char* key);
  2. int grib_is_defined(grib_handle* h, const char* key);

检查某个 key 的值是否是缺失值:

  1. int codes_is_missing(codes_handle* h, const char* key, int* err);
  2. int grib_is_missing(grib_handle* h, const char* key, int* err);

统计文件中的消息个数:

  1. int codes_count_in_file(codes_context* c, FILE* f,int* n);
  2. int grib_count_in_file(grib_context* c, FILE* f,int* n);

示例:codes_get

  1. #include <iostream>
  2. #include <eccodes.h>
  3. using namespace std;
  4. int main(int argc, char** argv)
  5. {
  6. if(argc < 2)
  7. {
  8. cout<<"Usage: "<<argv[0]<<" grib_file_path";
  9. return 1;
  10. }
  11. const char* file_path = argv[1];
  12. FILE* in = fopen(file_path, "rb");
  13. if(!in)
  14. {
  15. cout<<"ERROR: unable to open file "<<file_path<<endl;
  16. return 1;
  17. }
  18. int err = 0;
  19. codes_handle *h = nullptr;
  20. while((h=codes_handle_new_from_file(nullptr, in, PRODUCT_GRIB, &err)) != nullptr)
  21. {
  22. long data_date = -1;
  23. codes_get_long(h, "dataDate", &data_date);
  24. long type_of_level = -1;
  25. codes_get_long(h, "typeOfLevel", &type_of_level);
  26. long level = -1;
  27. codes_get_long(h, "level", &level);
  28. size_t size;
  29. codes_get_size(h, "values", &size);
  30. double *values = new double[size];
  31. codes_get_double_array(h, "values", values, &size);
  32. cout<<data_date<<" "<<type_of_level<<" "<<level<<" "<<size<<" "<<values[size-1]<<endl;
  33. delete [] values;
  34. codes_handle_delete(h);
  35. }
  36. fclose(in);
  37. return 0;
  38. }

示例:grib_get

将上面的代码替换为以 grib_ 开头的函数

  1. #include <iostream>
  2. #include <grib_api.h>
  3. using namespace std;
  4. int main(int argc, char** argv)
  5. {
  6. if(argc < 2)
  7. {
  8. cout<<"Usage: "<<argv[0]<<" grib_file_path";
  9. return 1;
  10. }
  11. const char* file_path = argv[1];
  12. FILE* in = fopen(file_path, "rb");
  13. if(!in)
  14. {
  15. cout<<"ERROR: unable to open file "<<file_path<<endl;
  16. return 1;
  17. }
  18. int err = 0;
  19. grib_handle *h = nullptr;
  20. while((h=grib_handle_new_from_file(nullptr, in, &err)) != nullptr)
  21. {
  22. long data_date = -1;
  23. grib_get_long(h, "dataDate", &data_date);
  24. long type_of_level = -1;
  25. grib_get_long(h, "typeOfLevel", &type_of_level);
  26. long level = -1;
  27. grib_get_long(h, "level", &level);
  28. size_t size;
  29. grib_get_size(h, "values", &size);
  30. double *values = new double[size];
  31. grib_get_double_array(h, "values", values, &size);
  32. cout<<data_date<<" "<<type_of_level<<" "<<level<<" "<<size<<" "<<values[size-1]<<endl;
  33. delete [] values;
  34. grib_handle_delete(h);
  35. }
  36. fclose(in);
  37. return 0;
  38. }

ecCodes 可以做更多的事情

ecCodes 的宗旨是提供高层次的 key 集合和不同的函数,用于检索或计算已加载 GRIB 消息中的额外信息。

对于不同的应用:

  • 只读key,返回数据值的均值和最值,分布经纬度信息
  • 计算经纬度、数据值的函数: codes_get_data
  • 获取指定坐标点最近的数据值 codes_grib_nearest_find
  • 根据 index 列表获取数据值 codes_get_double_elements