提问人:airvector222 提问时间:4/25/2014 更新时间:4/25/2014 访问量:537
fread 从二进制文件读取记录时返回< 1
fread Returns < 1 While Reading Record from Binary File
问:
我正在尝试从二进制文件中读取学生记录 (SREC)。该文件确保包含 l 个完整记录(上一次运行写入文件)。在我的输出中,我收到两次“错误:无法从文件中读取记录”语句,用于两条记录。顶部的 printf(Reading record, numR) 显示 3 次,所以我知道 while 循环在应该达到 eof 时被输入了 3 次。
有什么想法吗? 提前致谢!
/*Create and populate all 4 lists if lname list exists from previous usage*/
if((readL = fopen("last", "rb")) == NULL)
{
printf("\nNew file will be created after server terminates.\n");
created = 1;
}
else
{
created = 0;
/*Read in record from binary file*/
while(!feof(readL))
{
numR++;
printf("Reading record %d\n", numR);
/*Create new temporary SREC*/
newSREC = (SREC*)malloc(sizeof(SREC));
newSREC2 = (SREC*)malloc(sizeof(SREC));
newSREC3 = (SREC*)malloc(sizeof(SREC));
newSREC4 = (SREC*)malloc(sizeof(SREC));
/*Read in one record from file*/
if(fread(newSREC, sizeof(SREC), 1, readL) < 1)
{
newSREC2 = newSREC;
newSREC3 = newSREC;
newSREC4 = newSREC;
firstL = insert(newSREC, 1, firstL);
firstF = insert(newSREC2, 2, firstF);
firstS = insert(newSREC3, 3, firstS);
firstG = insert(newSREC4, 4, firstG);
}
else
{
printf("ERROR: Could not read record from file.\n");
}
}
fclose(readL);
}
答:
0赞
Deduplicator
4/25/2014
#1
EOF 的错误指示器仅在尝试读取超出范围时设置。
测试您阅读的位置是否成功读取。
在您的示例中,测试是否正好读取 1 条记录。
0赞
Chnossos
4/25/2014
#2
从手册页:fread
fread() 不区分文件末尾和错误,调用者必须使用 feof(3) 和 ferror(3) 来确定是哪个发生了。
将您的测试更改为以下内容:
while (fread(...) > 0)
// ...
if (ferror(file))
// an error happened
1赞
Jonathan Leffler
4/25/2014
#3
表面问题
从表面上看,此代码的反转了错误检测:
if (fread(newSREC, sizeof(SREC), 1, readL) < 1)
{
newSREC2 = newSREC;
newSREC3 = newSREC;
newSREC4 = newSREC;
firstL = insert(newSREC, 1, firstL);
firstF = insert(newSREC2, 2, firstF);
firstS = insert(newSREC3, 3, firstS);
firstG = insert(newSREC4, 4, firstG);
}
else
{
printf("ERROR: Could not read record from file.\n");
}
如果读取完整记录,则返回值为 1;否则为零。您应该使用:fread()
if (fread(newSREC, sizeof(SREC), 1, readL) == 1)
深入研究
循环不应该使用 — see while (!feof(file))
总是错的。您应该使用类似的东西:feof()
SREC srec;
while ((fread(&srec, sizeof(srec), 1, readL) == 1)
{
SREC *newSREC1 = malloc(sizeof(*newSREC1));
SREC *newSREC2 = malloc(sizeof(*newSREC2));
SREC *newSREC3 = malloc(sizeof(*newSREC3));
SREC *newSREC4 = malloc(sizeof(*newSREC4));
if (newSREC1 == 0 || newSREC2 == 0 || newSREC3 == 0 || newSREC4 == 0)
{
free(newSREC1);
free(newSREC2);
free(newSREC3);
free(newSREC4);
…report error…
break;
}
*newSREC1 = srec;
*newSREC2 = srec;
*newSREC3 = srec;
*newSREC4 = srec;
firstL = insert(newSREC1, 1, firstL);
firstF = insert(newSREC2, 2, firstF);
firstS = insert(newSREC3, 3, firstS);
firstG = insert(newSREC4, 4, firstG);
}
// Optional analysis of why the loop ended — feof() vs ferror() vs short read
代码会泄漏内存,就像永远不会缺少内存一样。分配 etc 后,它会用指向 的指针覆盖指针。任务
应为:newSREC2
newSREC1
*newSREC2 = *newSREC; // Original code — see above for revision
我注意到,您不能在一个数组中分配所有 4 条记录,因为您几乎肯定需要能够独立释放这 4 条记录。这在代码中留下了很多重复。
评论
while (!feof(readL))