[英]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.