2016-09-26 4 views
0
내가 바이너리 파일로 NumPy와 2 차원 float 배열을 쓴

작성 C에서 이진 파일을 읽고</p> <p><code>narr.tofile(open(filename,"wb"),sep="",format='f')</code></p> <p>를 사용하여 파이썬

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

이 데이터를 사용하여 C에서 같은를 검색하려고 배열은 원래 배열과 다른 값을 표시합니다. 내가 놓친 게 있니? 당신이 사용하는 그것은 수있는 시스템에 따라 감사

+4

확실하지 . – yano

+0

[mcve]를 작성하여 단일 플로트를 읽으십시오. 부작용으로 당신은 무슨 일이 일어나고 있는지 스스로 알아볼 수 있습니다. –

+0

'경고 : 다중 문자 상수'및'error : 'void *'에서 'float *'로의 무효 변환을 포함하여 C 스 니펫을 기반으로 컴파일 할 때 여러 오류 및 경고가 발생합니다. –

답변

0

최하위 바이트가 먼저를 저장하는 것을 의미 리틀 엔디안에서 ndarray.tofile() 출력은 numpy.byteswap()를 사용하고 파일로 변환하려고합니다. 형식 지정자 없이도 결과를 확인하십시오. 문서에서 지정자의 기본값은 format="%s"이고 서식 지정자 앞에 백분율 기호를 넣으려고 시도합니다 (예 : %f).

+0

예, 나는 그것을 알아 차 렸습니다 및 시도 %와 함께 시도했다. 문제는 여전히 남아 있습니다. 나는 그것이 데이터의 엔디안 - ness 때문인지 아직도 파악하려고 노력 중이다. byteswap()을 시도하고 잠시 후에 알려 드리겠습니다. –

0

np.save('foo.npy',narr) 통해 npy 형식으로 데이터를 저장하면 다른 방법이 있습니다. 이 데이터는 2 차원 고유 행렬로 데이터를 반환하는 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++ 파일

: 즉` "RB"해야한다, 그래서`, 그것은 _the_ 문제지만, fopen` '의 2 인자가`const를 숯불 *'인 경우

// 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; 
} 
+0

저는 실제로 일반적인 N x M 모양 행렬을 찾고 있습니다. 내 요구 사항에 맞지 않습니다. –