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