zzu
zzu

Reputation: 268

hold position of FILE pointer before fseek()

I am trying to write a C function that reads the first line of text from a file, then uses fseek() and ftell() to get the size of the remainder of the file (the file minus the first line).

My idea was to use a second FILE *fp1 to grab the position of the original FILE *fp, and send fp1 to the end of the file with fseek(), so that I wouldn't have to move my original fp and lose its position.

Here's my code. The compiler is telling me I can't assign fp1 to fp because fp1 is a FILE* and fp is a struct FILE*.

Can I achieve what I'm trying to do this way?

 FILE *fp, fp1;
 fp = fopen(filename, "r");
 if (!fp)
     return 0;

 fscanf(fp, "%1d", m); //Lines 15-18 read the first line of the file
 fscanf(fp, "%*1c");
 fscanf(fp, "%1d", n);
 fscanf(fp, "%*1c");
 fp1 = fp;         //<---------- This is my problem.
                   //how do I set fp1 to the same place in the
                   //file as fp?

 fseek(fp1, 0, SEEK_END);
 *file_size = ftell(fp1);

Upvotes: 0

Views: 2380

Answers (2)

chqrlie
chqrlie

Reputation: 144695

Your definition does not define 2 FILE * pointers:

FILE *fp, fp1;

fp is a FILE *, but fp1 is defined as a FILE type.

You cannot define FILE objects this way, they should only be obtained from fopen(). Their state cannot be saved by making a copy of the FILE object, it is way too complex for this and uses other resources in addition to the FILE object, which may be an incomplete type.

The good news is you can save the current offset in fp with ftell() and seek to the end to attempt to get the file size, and then restore the stream position with another call to fseek():

long saved = ftell(fp);
*file_size = -1;  // file size may be impossible to retrieve
if (fseek(fp, 0, SEEK_END) != -1) {
    *file_size = ftell(fp);
}
fseek(fp, saved, SEEK_SET);

But you should note that this method is not reliable:

  • it is not guaranteed for text files.
  • it may not work for devices, pipes, the terminal, special files...

You should try and modify your method so it does not need to know the file size.

Upvotes: 2

TNW
TNW

Reputation: 726

This just copies the pointer to file handle. The proper way is to save ftell result before you move, and after moving to end of file - move back again.

So:

long saved = ftell(fp);
fseek(fp, 0, SEEK_END);
*file_size = ftell(fp);
fseek(fp, saved, SEEK_SET);

Upvotes: 5

Related Questions