在函数调用之间保留文件指针

时间:2013-04-20 18:23:39

标签: c file-io binaryfiles

我有一个代码,我几次访问二进制文件。每次调用该函数时,它都会打开文件进行读取,并且只读取所需的字节数(每次都说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;
}

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

4 个答案:

答案 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;
}

答案 1 :(得分:6)

快速的经验法则是

如果你正确地分离职能之间的责任

,生活会变得更容易

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

在这种情况下,赋予readBinary函数管理FILE和读取数据的责任都太大了。

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

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

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

请注意,如果您删除“打开文件”,readBinary功能只是对fread的调用。

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

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

现在,这可能会给来电者带来太多责任。只需让调用者接受FILE*作为参数,并将文件管理职责交给其调用者。 或者呼叫者的呼叫者的呼叫者,取决于管理文件生命周期的合理位置。

答案 2 :(得分: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,除非您想要添加错误打印等内容。

答案 3 :(得分: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;
}