繁体   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