0

I'm using the following code to read a binary file and use a struct to output the data. However, I know my data consist of only one record, and it seems to be printing out many records. I'm wondering why this might be?

 FILE *p;
 struct myStruct x;
 p=fopen("myfile","rb");
 //printf("Rcords of file:\n");
 while(1)
 {
     fread(&x,sizeof(x),1,p);
     if(feof(p)!=0)
         break;
        printf("\n\nID:%ld",x.ID);
    }
 fclose(p);
 return 0;

The struct is fairly normal like this:

struct myStruct
{
    int ID;     
    char name[100];
}
15
  • 1
    char name; makes no sense. Names rarely consist of a single char. Commented Sep 17, 2016 at 8:15
  • 1
    How big is the file? What does fread return? Commented Sep 17, 2016 at 8:17
  • 2
    I'm completely unhappy with your question here, even with your edit. Post a minimal reproducible example and I may be ready to negotiate. Commented Sep 17, 2016 at 8:17
  • 1
    You can still tell us about the data file: ls -la myfile and wc myfile. Also what is th return value of fread(). How do you expect your program to work correctly if you don't check the results of your functions. Commented Sep 17, 2016 at 8:23
  • 1
    Does fread return 1 always? Commented Sep 17, 2016 at 8:27

2 Answers 2

2

Use %d instead of %ld to print an int

And take a look to Why is “while ( !feof (file) )” always wrong?

A struct haves a fixed size, you can use ftell to get the size of the file and then divide using the size of the struct in order to get the number of records, also, always check the result of those functions.

Something like:

FILE *file;
long size;
size_t count, records;

file = fopen("myfile", "rb");
if (file == NULL) {
    perror("fopen");
    return 0;
}
if (fseek(file, 0, SEEK_END) == -1) {
    perror("fseek");
    return 0;
}
size = ftell(file);
if (size == -1) {
    perror("ftell");
    return 0;
}
if (fseek(file, 0, SEEK_SET) == -1) {
    perror("fseek");
    return 0;
}
records = size / sizeof(x);
for (count = 0; count < records; count++) {
     if (fread(&x, sizeof(x), 1, file) == 1) {
         printf("\n\nID:%d",x.ID); /* %d instead of %ld */
     } else {
         break;
     }
}

But notice that you are always writing to the same variable on the stack.

EDIT:

How do you store the struct in the file?

I'm not storing it, a program is.

If it is not yours (you don't build the file using the same struct) then you can't know which is the sizeof(x) inside the file, read about structure padding and packing.

Sign up to request clarification or add additional context in comments.

21 Comments

hmmn where is x created?
hmmm where is your minimal, complete and verfiable example? thats a way to avoid using the almost always wrong feof
Hmmn, I still get multiple prints with your version. Clearly something is wrong with the way we are accessing this data. There is only one record, and it is printing many. Could this be because it's reading bytes? The example is about as minimal as I could get it. The file I cannot upload because its binary
And how do you know the size of the struct in the file if it is not yours?
@user3121023, right! ftell result must be a multiple of sizeof(x)
|
1

Use more protection. Test the result of functions.

 FILE *p;
 struct myStruct x;
 p=fopen("myfile","rb");
 assert(p); // Insure file opened

 while(1) {
   size_t n = fread(&x, sizeof(x), 1, p);
   // feof() is insufficient, 
   // fread() can fail due to input errors too and not set end-of-file condition
   // if(feof(p)!=0)
   if (n == 0) {
     break;
   }
   // printf("\n\nID:%ld",x.ID);
   printf("\n\nID:%d", x.ID);  // Use matching specifier
   fflush(stdout); // Insure output occurs promptly
 }
 fclose(p);
 return 0;

Since OP's code had a mis-matched printf specifier, it indicates that either warnings are not fully enabled or OP is using a weak compiler. Suggest fixing that to save time.

2 Comments

Hi, it still prints out multiple lines, whereas I know that ID is only one value. In other words, it is not reading that ID part of the struct, but the whole struct. How do I make it just for the ID part?
@Ke. " In other words, it is not reading that ID part of the struct," is contradicted by "but the whole struct.". Code cannot read the while struct without reading the filed ID. I suspect the true code and what you have posted here differ. 2 ideas: The x in fread(&x, sizeof(x), 1, p); is really a pointer or the file your are reading is much bigger than thought. What is the file size?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.