在cython中使用C函数读写文件中的数组

Reading and writing an array in a file using C functions in cython

我正在 cython 中实例化一个 class。我想声明一个实例,它是 float 值的数组,通过使用给定函数计算它一次,并使用 c 函数将其保存在二进制文件中。对于我的 class 的进一步调用,如果输入文件已经存在,实例将通过从文件中读取数组来声明,否则它将再次计算它。

import numpy as np
cimport numpy as np
cimport cython

from libc.stdio cimport FILE, fopen, fwrite, fscanf, fclose, fseek, SEEK_END, ftell, stdout, stderr
cdef extern from "math.h":
    double exp(double) nogil
    double log(double) nogil

cdef class Hit(object):
    cdef public double[::1] zs, Da
    cdef char* path

    def __cinit__(self, zs=None, path=None):
        if path is None:
           raise ValueError("Could not find a path to the file which contains the table of distances")
        else:
           self.path=path
        if zs is None:
           raise ValueError("You must give an array which contains the steps!")
        self.zs=zs
        cdef Py_ssize_t i, N
        N=len(self.zs)
        cdef FILE *ptr_fr
        cdef FILE *ptr_fw
        cdef double[::1] ptr_d = np.empty((N,))
        ptr_fr = fopen(self.path, "rb")
        ptr_fw = fopen(self.path, "wb")
        if (ptr_fr==NULL):
           print "I/O Error: cannot open file {}".format( self.path)  
           for i from N > i >= 0:
               ptr_d[i]=log(self.zs[i]+1.) /(1- self.zs[i])**0.5    
           if (ptr_fw == NULL):
               print "Unable to open file!\n"
           else:
               print "Opened file successfully for writing.\n"
               fwrite(<void*>&ptr_d[0], sizeof(double), N, ptr_fw)
               fclose(ptr_fw)
               self.Da = ptr_d

        else: 
           for i from N > i >= 0:
               fscanf(ptr_fr,"%f", &ptr_d[i])

           fclose(ptr_fr)
           self.Da = ptr_d

当我第二次 运行 我的代码时 returns 从文件读取到指针的值是正确的,但是我认为我将指针分配给内存视图的方式有问题,因为 self.Da 实例中的所有值都是零。有什么建议吗?!!

你应该换行:

ptr_fw = fopen(self.path, "wb")

为了

ptr_fw = fopen(self.path, "ab")

http://www.cplusplus.com/reference/cstdio/fopen/

[w option] write: Create an empty file for output operations. If a file with the same name already exists, its contents are discarded and the file is treated as a new empty file.

同时

[a option] append: Open file for output at the end of a file. Output operations always write data at the end of the file, expanding it. Repositioning operations (fseek, fsetpos, rewind) are ignored. The file is created if it does not exist.

括号是我的。打开后,您正在删除 path 中的内容。所以下一次,你打开了一个空文件。

更新:(我在您的第一次实施中做了这两项更改)

另外,改变你的

fwrite(<void*>&ptr_d[0], sizeof(double), N, ptr_fw)

为:

       for i in range(N):
           fprintf(ptr_fw, "%lf\n", ptr_d[N-i-1])

你读的是格式化的,但写的是未格式化的(记得从 stdio 导入 fprintf,上面的改变也很重要)。

我自己的问题的答案是:

import numpy as np
cimport numpy as np
cimport cython
from libc.stdio cimport FILE, fopen, fwrite, fscanf, fclose, fprintf, fseek, ftell, SEEK_END, rewind, fread
from numpy cimport float64_t
from libc.stdlib cimport malloc, free
cdef extern from "math.h":
    double exp(double) nogil
    double log(double) nogil

cdef class Hit(object):
    cdef public double[::1] zs,  Da
    cdef char* path

    @cython.boundscheck(False)
    @cython.cdivision(True)
    @cython.wraparound(False)
    @cython.nonecheck(False)
    def __cinit__(self, path=None, zs=None):
        if path is None:
           raise ValueError("Could not find a path to the file which contains the table of distances")
        else:
           self.path=path

        if zs is None:
           raise ValueError("You must give an array which contains the steps!")
        self.zs=zs

        cdef Py_ssize_t i, N, lSize
        N=len(np.ascontiguousarray(self.zs))
        print "Input file should have ",N
        cdef FILE *ptr_fr
        cdef FILE *ptr_fw
        cdef size_t result
        cdef double *ptr_d= <double *>malloc(N * sizeof(double))
        ptr_fr = fopen(self.path, "rb")        
        if (ptr_fr==NULL):
           print "I/O Error: cannot open file {}".format( self.path) 
           for i from N > i >= 0:
               ptr_d[i]=log(self.zs[i])
               print ptr_d[i]
           ptr_fw = fopen(self.path, "wb")
           if (ptr_fw == NULL):
               print "Unable to open file!\n"

           else:

               print "Opened file successfully for writing.\n"
               fwrite(ptr_d, sizeof(double), N, ptr_fw)
               fclose(ptr_fw)
               self.Da = np.asarray(<double[:N]>ptr_d)
        else: 
           fseek (ptr_fr , 0 , SEEK_END)
           lSize = ftell (ptr_fr)
           print lSize
           rewind (ptr_fr)
           result=fread(ptr_d,sizeof(double),lSize ,ptr_fr )
           for i from N > i >= 0:
               print ptr_d[i]
           fclose(ptr_fr)
           self.Da = np.asarray(<double[:N]>ptr_d)
        print np.ascontiguousarray(self.Da)

        free(ptr_d)