cgribeccodesgrib-api

ECCODES C API : updating keys offset, count and countTotal


I am using the codes_grib_multi_handle_write() function to create a multi message grib by iterating over a h = codes_grib_handle_new_from_samples(NULL,"GRIB2"). Each handle is added to the multi handle mh with the function codes_grib_multi_handle_append(h, startSection, mh) It seems that the "offset" key of the messages of the multigrib obtained remains at 0 and that the "count" key remains at 1. Only the "countTotal" key is incremented. Is there a way to see these keys update based on the number of messages present? I tried :

// set offset
size_t totalLength = 0, size2 = 0;
const void* buffer = NULL;

CODES_CHECK(codes_get_message_size(h,&totalLength),0);
buffer=(unsigned char*)malloc(totalLength*sizeof(char));

CODES_CHECK(codes_get_message(h, &buffer, &size2),0);
fprintf(stderr,"size in loop : %ld\n", size2);
//CODES_CHECK(codes_set_long(h, "offset", offset),0); //=> pb en read only !!
//CODES_CHECK(codes_set_long(h, "count", count),0); //=> pb en read only !!
offset += size2;
count += 1;

Solution

  • The codes_grib_multi_handle_write() and codes_grib_multi_handle_append() functions are not suitable for writing multiple messages in a single file. It is used to write a multi-field grib. This is why it is necessary to use the functions codes_get_message and fwrite. Here is a quick example kindly given by the ECMWF team, thanks to them:

    #include <stdio.h>
    #include "eccodes.h"
    int main(int argc, char* argv[])
    {
        FILE* in                    = NULL;
        FILE* out                   = NULL;
        codes_handle* h = NULL;
        const void* buffer          = NULL;
        size_t size                 = 0;
        int err                     = 0;
    
        if (argc != 3) return 1;
    
        codes_grib_multi_support_on(NULL); /* NOTA BENE */
    
        in  = fopen(argv[1], "rb");
        out = fopen(argv[2], "wb");
    
        /* loop over the messages in the source grib and copy them */
        while ((h = codes_handle_new_from_file(0, in, PRODUCT_GRIB, &err)) != NULL) {
            CODES_CHECK(codes_get_message(h, &buffer, &size), 0);
            if (fwrite(buffer, 1, size, out) != size) {
                perror(argv[1]);
                return 1;
            }
            codes_handle_delete(h);
        }
        fclose(out);
        fclose(in);
        return 0;
    }