什么是二进制文件的 EOF?
what is the EOF of binary file?
我的程序需要从一个二进制文件读取一个链表,这个函数做得很好并为它分配了正确的内存,但由于某种原因它在中断之前做了另一个循环。尝试为它寻找一个好的解决方案但没有运气,链表中的最后一个结构变得垃圾。
结构:
typedef struct
{
char id[10];
char * first_name;
char * last_name;
int age;
char gender;
char * username;
char * password;
char * description;
int hobbies[4];
struct Person * next_client;
}Person;
这是一些代码:
Person * input_from_file(Person * member)
{
int str_size;
Person * clients_start = NULL;
FILE * filePointerRead;
filePointerRead = fopen("input.bin", "rb");
if (filePointerRead != NULL){
while (1){
member = NULL;
member = (Person*)malloc(sizeof(Person));
fread(&member->id, sizeof(char), ID_DIGITS + 1, filePointerRead);
fread(&str_size, sizeof(int), 1, filePointerRead);
member->first_name = (char*)malloc(str_size*sizeof(char));
fread(member->first_name, sizeof(char), str_size, filePointerRead);
//more reading from file
member->next_client = NULL;
clients_start = receive_clients_info(clients_start, member); //function to put the received struct from file to end of the linked list
if (feof(filePointerRead))
break;
}
fclose(filePointerRead);
}
return clients_start;
}
检查 fread()
而不是 foef()
,Stack Overflow 上有很多关于此的答案,feof()
return 当设置 EOF 指示器时为真,fread()
将在读取超过文件末尾时设置它。
fread()
将 return 0
或到达文件末尾时少于请求的字节数,但您的程序需要一个额外的循环,其中 fread()
尝试读取文件末尾之后,它将设置 EOF
指示符。
看到这个“while( !feof( file ) )” is always wrong
调用 feof
的问题在于它不会 return 你 "true" 除非你在 EOF
时尝试读取。换句话说,如果您的文件恰好有 100 个字节,并且您已经成功地尝试读取恰好 100 个字节,则 feof
将 return "false" 直到您尝试至少再读取一个字节。
这就是为什么你应该避免 feof
而要检查 fread
的 return 值的原因,它告诉你从文件中读取了多少字节:
if (fread(&member->id, sizeof(char), ID_DIGITS + 1, filePointerRead) != ID_DIGITS + 1) {
// The code above knows that sizeof(char) is always 1.
// For other data types you need to compute the actual size
// by multiplying sizeof(T) by the number of items that you read.
break;
}
在所有调用 fread
的地方做同样的事情。
与 !=
的比较有效,因为 fread
始终 return 是您在完成请求时传递的确切大小:
Upon successful completion, fread()
shall return the number of elements successfully read which is less than nitems
only if a read error or end-of-file is encountered.
您遇到的问题是 feof() 在设置文件的 EOF 标志之前不会 return 为真,并且在尝试读取文件之前不会设置文件的 EOF 标志失败,因为文件中没有剩余数据可供读取。
这是一个例子:假设文件中有 1 个字节,并且您有一个循环,一次读取一个字节的文件。
第一次通过循环,读取一个字节并返回给程序。如果程序测试 feof() 它仍然会 return FALSE 因为读取文件成功。
第二次循环,文件中的所有字节都已读取,因此读取了 0 个字节并 returned 到程序,此时设置了 EOF 标志,因为正在读取文件由于到达结尾而失败。此时 feof() 将 return TRUE.
在我的示例中,即使文件中只有一个字节,您也执行了两次循环。您的代码也发生了同样的情况。
要解决该问题,请始终检查 fread() 调用的结果。它 returns 读取的项目数(不是字节数)。顺便说一句,fread() 将始终读取整个项目而不是部分项目。如果 fread() returns 比您预期的少,则跳出循环。通常,您会跳出循环,因为您已到达文件末尾,但也有可能出现其他错误——也许有人将电源线拔到了外部硬盘驱动器上。如果你想知道为什么 fread() 没有读取任何东西,你可以使用 feof() 或 ferror()。
any easy way to accomplish the task is:
calculating the total length of each complete record in the file
(from your code, I assume all records are the same length)
fopen( ..inputfile.. )
if fopen not successful,
then
perror()
exit( EXIT_FAILURE );
endif
// implied else, fopen successful
while(completelength == fread( the complete length into a local buffer))
{
...extract each field from local buffer into struct...
...place struct into linked list...
}
//when get here, reading/building linked list is done
fclose( inputfile )
...
我的程序需要从一个二进制文件读取一个链表,这个函数做得很好并为它分配了正确的内存,但由于某种原因它在中断之前做了另一个循环。尝试为它寻找一个好的解决方案但没有运气,链表中的最后一个结构变得垃圾。
结构:
typedef struct
{
char id[10];
char * first_name;
char * last_name;
int age;
char gender;
char * username;
char * password;
char * description;
int hobbies[4];
struct Person * next_client;
}Person;
这是一些代码:
Person * input_from_file(Person * member)
{
int str_size;
Person * clients_start = NULL;
FILE * filePointerRead;
filePointerRead = fopen("input.bin", "rb");
if (filePointerRead != NULL){
while (1){
member = NULL;
member = (Person*)malloc(sizeof(Person));
fread(&member->id, sizeof(char), ID_DIGITS + 1, filePointerRead);
fread(&str_size, sizeof(int), 1, filePointerRead);
member->first_name = (char*)malloc(str_size*sizeof(char));
fread(member->first_name, sizeof(char), str_size, filePointerRead);
//more reading from file
member->next_client = NULL;
clients_start = receive_clients_info(clients_start, member); //function to put the received struct from file to end of the linked list
if (feof(filePointerRead))
break;
}
fclose(filePointerRead);
}
return clients_start;
}
检查 fread()
而不是 foef()
,Stack Overflow 上有很多关于此的答案,feof()
return 当设置 EOF 指示器时为真,fread()
将在读取超过文件末尾时设置它。
fread()
将 return 0
或到达文件末尾时少于请求的字节数,但您的程序需要一个额外的循环,其中 fread()
尝试读取文件末尾之后,它将设置 EOF
指示符。
看到这个“while( !feof( file ) )” is always wrong
调用 feof
的问题在于它不会 return 你 "true" 除非你在 EOF
时尝试读取。换句话说,如果您的文件恰好有 100 个字节,并且您已经成功地尝试读取恰好 100 个字节,则 feof
将 return "false" 直到您尝试至少再读取一个字节。
这就是为什么你应该避免 feof
而要检查 fread
的 return 值的原因,它告诉你从文件中读取了多少字节:
if (fread(&member->id, sizeof(char), ID_DIGITS + 1, filePointerRead) != ID_DIGITS + 1) {
// The code above knows that sizeof(char) is always 1.
// For other data types you need to compute the actual size
// by multiplying sizeof(T) by the number of items that you read.
break;
}
在所有调用 fread
的地方做同样的事情。
与 !=
的比较有效,因为 fread
始终 return 是您在完成请求时传递的确切大小:
Upon successful completion,
fread()
shall return the number of elements successfully read which is less thannitems
only if a read error or end-of-file is encountered.
您遇到的问题是 feof() 在设置文件的 EOF 标志之前不会 return 为真,并且在尝试读取文件之前不会设置文件的 EOF 标志失败,因为文件中没有剩余数据可供读取。
这是一个例子:假设文件中有 1 个字节,并且您有一个循环,一次读取一个字节的文件。
第一次通过循环,读取一个字节并返回给程序。如果程序测试 feof() 它仍然会 return FALSE 因为读取文件成功。
第二次循环,文件中的所有字节都已读取,因此读取了 0 个字节并 returned 到程序,此时设置了 EOF 标志,因为正在读取文件由于到达结尾而失败。此时 feof() 将 return TRUE.
在我的示例中,即使文件中只有一个字节,您也执行了两次循环。您的代码也发生了同样的情况。
要解决该问题,请始终检查 fread() 调用的结果。它 returns 读取的项目数(不是字节数)。顺便说一句,fread() 将始终读取整个项目而不是部分项目。如果 fread() returns 比您预期的少,则跳出循环。通常,您会跳出循环,因为您已到达文件末尾,但也有可能出现其他错误——也许有人将电源线拔到了外部硬盘驱动器上。如果你想知道为什么 fread() 没有读取任何东西,你可以使用 feof() 或 ferror()。
any easy way to accomplish the task is:
calculating the total length of each complete record in the file
(from your code, I assume all records are the same length)
fopen( ..inputfile.. )
if fopen not successful,
then
perror()
exit( EXIT_FAILURE );
endif
// implied else, fopen successful
while(completelength == fread( the complete length into a local buffer))
{
...extract each field from local buffer into struct...
...place struct into linked list...
}
//when get here, reading/building linked list is done
fclose( inputfile )
...