Reading binary file in c written in python
<p>I wrote numpy 2 dimensional float array as a binary file using </p>

<p><code>narr.tofile(open(filename,"wb"),sep="",format='f')</code> </p>

<p>and try to retrieve the same in c using</p>

<pre><code>FILE* fin = fopen(filename,"rb") 
float* data = malloc(rows*2*sizeof(float));
fread(data, sizeof(float), rows*2, fin);
</code></pre>

<p>This data array when printed shows different values than original array. Am I missing something?
Thanks</p>

<p>Here is another way if you save your data in npy format through <code>np.save('foo.npy',narr)</code>. It is a (writer and) reader for 2D npy files that returns its data as a two dimensional Eigen matrix. Note that the code does lots of assumptions and only works for 2D arrays saved with the standard np save() options. </p>

<pre><code>// npymatrix.h
#ifndef NPYMATRIX_H
#define NPYMATRIX_H

#include &lt;Eigen/Eigen&gt;

// Routines for saving and loading Eigen matrices as npy files.
int npywrite(Eigen::MatrixXd&amp; mat, const char *filename, bool do_flip_y);
int npyread(const char *filename,
            // output
            Eigen::MatrixXd&amp; mat);

#endif /* NPYMATRIX */
</code></pre>

<p>And the C++ file:</p>

<pre><code>// npymatrix.cc

#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
#include "npymatrix.h"

using namespace Eigen;

enum {
    FLOAT8,
    FLOAT4,
    INT8
};

static const int data_size[] = {8,4, 1};

int npywrite(MatrixXd&amp; mat, const char *filename, bool do_flip_y)
{
    FILE *fh = fopen(filename, "wb");
    if (!fh)
        return -1;

    // Write header and version number to file
    fwrite("\223NUMPY"
           "\001\000"
           , 1, 8, fh);
    char header[100];
    sprintf(header,
            "{'descr': '&lt;f8', 'fortran_order': False, 'shape': (%d, %d), } \n",
            mat.rows(),
            mat.cols());
    unsigned short header_len = strlen(header);
    fwrite(&amp;header_len, 2, 1, fh);
    fwrite(header, header_len, 1, fh);

    // Is there a faster way??
    for (int row_idx=0; row_idx&lt;mat.rows(); row_idx++) {
        for (int col_idx=0; col_idx&lt;mat.cols(); col_idx++) {
            int r_idx = row_idx;
            if (do_flip_y)
                r_idx = mat.rows()-1-r_idx;
            double v = mat(r_idx, col_idx);
            fwrite(&amp;v, sizeof(double), 1, fh);
        }
    }

    fclose(fh);
    return 0;
}

static const char *find_next_alphanum(const char *p)
{
    while(*p &amp;&amp; (!isalnum(*p)))
        p++;
    return p;
}

static const char *find_next_string_after(const char *p, const char *token)
{
    p = strstr(p, token);
    if (!p)
        return p;
    return p + strlen(token);
}

static const char *find_next_alnum_after(const char *p)
{
    while(*p and isalnum(*p))
        p++;
    return p;
}

static char *strdup_to_delim(const char *p, const char *delim)
{
    const char *pstart = p;

    while(*p &amp;&amp; !strchr(delim, *p)) 
        p++;
    return strndup(pstart, p-pstart);
}

int npyread(const char *filename,
            // output
            MatrixXd&amp; mat)
{
    FILE *fh = fopen(filename, "rb");

    // Magic bytes
    char magic_bytes[6], version[2];
    fread(magic_bytes, 1, 6, fh);

    // Version
    fread(version, 1, 2, fh);

    // Header len
    short header_len;
    fread(&amp;header_len, 1, 2, fh);

    // Read the header
    char *header = new char[header_len];
    fread(header, 1, header_len, fh);

    // parse the header. This is ugly but works for a standard header...
    const char *p = header;
    p = find_next_string_after(p, "descr");
    p = find_next_alphanum(p+1);
    char *descr = strdup_to_delim(p, "'\"");

    p = find_next_string_after(p, "fortran_order");
    p = find_next_alphanum(p+1);
    char *fortran_order = strdup_to_delim(p, ",");

    p = find_next_string_after(p, "shape");
    p = find_next_alphanum(p+1);
    char *shape = strdup_to_delim(p, ")");

    int height = atoi(shape);
    int width = atoi(find_next_alphanum(find_next_alnum_after(shape)));

    // Decode the type
    int dtype=-1;
    if (strcmp("&lt;f8", descr)==0
        || strcmp("f8", descr)==0
        ) {
        dtype=FLOAT8;
    }
    else if (strcmp("&lt;f4", descr)==0
             || strcmp("f4", descr)==0) {
        dtype=FLOAT4;
    }
    else {
        printf("Unsupported data type: %s!\n", descr);
        return -1;
    }
    int pixel_size = data_size[dtype];
    mat.setZero(height, width);
    for (int row_idx=0; row_idx&lt;height; row_idx++) {
        for (int col_idx=0; col_idx&lt;width; col_idx++) {
            unsigned char v[8];
            double gl;
            fread(v, 1, pixel_size, fh);
            switch(dtype) {
            case FLOAT8:
                gl = *((double*)v);
                break;
            case FLOAT4:
                gl = *((float*)v);
                break;
            default:
                gl = *((unsigned char*)v);
                break;
            }
            mat(row_idx,col_idx) = gl;
        }
    }

    fclose(fh);
    free(shape);
    free(descr);
    free(fortran_order);
    delete [] header;

    return 0;
}
</code></pre>

python c arrays numpy