2013-04-20 58 views
3

我有一个代码,我正在访问一个二进制文件几次。每次我调用该函数时,它都会打开文件进行读取,并只读出所需的字节数(每次说明为n字节)。保存函数调用之间的文件指针

二进制文件包含时间序列数据,我希望能够做的是通过循环运行函数调用,并且每次调用函数打开同一个文件时,都需要读取出下一块数据,我不希望每次都重置文件指针。有没有办法做到这一点?

函数看起来像这样:

int readBinary(float *binImage, int gelements) { 
    imageFile = fopen("tmpImageFile", "r"); 
    if (imageFile == NULL) { 
     fprintf(stderr, "Error opening file\n"); 
     return (1); 
    } 
    fread(binImage, sizeof(float), gelements, imageFile); 
    return 0; 
} 

而且在我主要的代码,我想通过一个循环来运行它,给它每一次大小gelements的阵列binImage。如果这是可以避免的,我宁愿不给它一个大小为gelements * nLoop的数组。

+3

为什么你不断重新打开文件?只需打开一次并继续使用它。 – Barmar 2013-04-20 18:26:21

回答

6

拇指快速规则

生活变得更容易,如果功能之间你正确地分别承担的责任”

的生活,如果你使用静态或全局变量变得复杂 ”。

在这种情况下,给予readBinary函数管理FILE和读取数据的责任过多。

请注意,该功能不会关闭句柄。

如果句柄是函数中的局部静态,那么将无法关闭它。 这也意味着函数将被永久锁定为仅使用“tmpImageFile”(从函数的签名或缺少文档中不会立即显示)

如果句柄是全局的,则可能过早关闭它。

请注意,如果您删除“打开文件”职责readBinary函数只是致fread

处理此问题的最佳方法是完全跳过readBinary函数。

你说你有一个循环读取数据的调用者。 让此调用者负责打开FILE,直接在循环中使用fread,并在完成后关闭文件。

现在,这可能会给调用者太多的责任。只需让主叫方接受FILE*作为参数,并将文件管理责任交给主叫方。 或调用者的调用者的调用者,取决于管理文件的生命周期的意义。

1

您可以使文件指针为静态并将其初始化为NULL。然后下一次如果它不是NULL,则它包含打开的文件。同时关闭文件时,确保将其重新设置为NULL。同样也有一个全球性的指针做也使您保留文件指针

int readBinary(float *binImage, int gelements) { 
static imageFile = NULL; 
if(imageFile == NULL) imageFile = fopen("tmpImageFile", "r"); 
if (imageFile == NULL) { 
    fprintf(stderr, "Error opening file\n"); 
    return (1); 
} 
fread(binImage, sizeof(float), gelements, imageFile); 
return 0; 
} 
6

使用一个静态变量:

int readBinary(float *binImage, int gelements) { 
    static FILE *imageFile = NULL; 
    if (imageFile == NULL) { 
     imageFile = fopen("tmpImageFile", "r"); 
     if (imageFile == NULL) { 
      perror("Error opening file: "); 
      return (1); 
     } 
    } 
    fread(binImage, sizeof(float), gelements, imageFile); 
    return 0; 
} 
3

我会通过FILE*作为参数传递给函数:

int readBinary(float *binImage, int gelements, FILE *imageFile) { 
    int bytes = fread(binImage, sizeof(float), gelements, imageFile); 
    return bytes != -1 ? 0 : 1; 
} 

我还为fread返回值添加了简单检查并将其转换为您的返回值约定。虽然这个功能看起来很简单,但您可以直接拨打fread,除非您想添加错误打印等内容。