簡體   English   中英

用Python編寫的C中讀取二進制文件

[英]Reading binary file in c written in python

我使用以下方式將numpy 2維浮點數組編寫為二進制文件

narr.tofile(open(filename,"wb"),sep="",format='f')

並嘗試使用c檢索相同的內容

FILE* fin = fopen(filename,"rb") 
float* data = malloc(rows*2*sizeof(float));
fread(data, sizeof(float), rows*2, fin);

打印時此數據數組顯示的值與原始數組不同。 我想念什么嗎? 謝謝

這可能取決於您使用的系統, ndarray.tofile()以little-endian ndarray.tofile()輸出,這意味着最低有效字節先存儲 ,然后嘗試使用numpy.byteswap()然后轉換為文件。 也可以嘗試不使用格式說明符來查看結果。 文檔指出,說明符的默認值為format="%s" ,請嘗試在格式說明符之前放置百分比符號,例如%f

如果通過np.save('foo.npy',narr)將數據保存為npy格式,這是另一種方法。 它是2d npy文件的(寫入器)讀取器,將其數據作為二維本征矩陣返回。 請注意,該代碼有很多假設,並且僅適用於使用標准np save()選項保存的2D數組。

// npymatrix.h
#ifndef NPYMATRIX_H
#define NPYMATRIX_H

#include <Eigen/Eigen>

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

#endif /* NPYMATRIX */

和C ++文件:

// npymatrix.cc

#include <stdio.h>
#include <string.h>
#include "npymatrix.h"

using namespace Eigen;

enum {
    FLOAT8,
    FLOAT4,
    INT8
};

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

int npywrite(MatrixXd& 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': '<f8', 'fortran_order': False, 'shape': (%d, %d), } \n",
            mat.rows(),
            mat.cols());
    unsigned short header_len = strlen(header);
    fwrite(&header_len, 2, 1, fh);
    fwrite(header, header_len, 1, fh);

    // Is there a faster way??
    for (int row_idx=0; row_idx<mat.rows(); row_idx++) {
        for (int col_idx=0; col_idx<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(&v, sizeof(double), 1, fh);
        }
    }

    fclose(fh);
    return 0;
}

static const char *find_next_alphanum(const char *p)
{
    while(*p && (!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 && !strchr(delim, *p)) 
        p++;
    return strndup(pstart, p-pstart);
}

int npyread(const char *filename,
            // output
            MatrixXd& 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(&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("<f8", descr)==0
        || strcmp("f8", descr)==0
        ) {
        dtype=FLOAT8;
    }
    else if (strcmp("<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<height; row_idx++) {
        for (int col_idx=0; col_idx<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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM