Determining EOF using fseek()?

O

Orion

Hey,

I was wondering if it was possible to determine if you hit 'EOF' using
fseek? I'm using fseek to traverse through the file from start to end
and capturing the data into a linked list structure. However, my loop
doesn't seem to work well - it totally fumbles out actually:

while ((a = fseek(fp,0,SEEK_CUR)) == 0){
// code here
}

Its quite important for me not to disrupt the current position of the
cursor since I rely on that to fetch the data from the text file. I
thought that the loop would work fine since fseek only returns a
non-zero integer on an error but unfortunately this is not the case.
Anyone with suggestions with using fseek() or some other function?

Any help would be greatly appreciated! Thanks.
 
V

Villy Kruse

Hey,

I was wondering if it was possible to determine if you hit 'EOF' using
fseek? I'm using fseek to traverse through the file from start to end
and capturing the data into a linked list structure. However, my loop
doesn't seem to work well - it totally fumbles out actually:

while ((a = fseek(fp,0,SEEK_CUR)) == 0){
// code here
}

I wouldn't expect this would ever return an error as long as fp is a valid
FILE pointer representing a seekable file. The normal way to determine
eof is to read from the file and see if it returns an eof indication.



Villy
 
E

Eric Sosman

Orion said:
Hey,

I was wondering if it was possible to determine if you hit 'EOF' using
fseek? I'm using fseek to traverse through the file from start to end
and capturing the data into a linked list structure. [...]

If you're reading the whole file "from start to end," why
are you using fseek() at all? Just keep calling fgets() or
fread() or whatever you're using to soak up the data, and when
you get to end-of-file the function will tell you so[*] by
returning the value EOF.

[*] The EOF return value can also indicate an actual I/O
error rather than end-of-file. For belt-and-suspenders
certainty, you can use feof() or ferror() to figure out
what the EOF value actually meant.
 
K

Karthiik Kumar

Orion said:
Hey,

I was wondering if it was possible to determine if you hit 'EOF' using
fseek? I'm using fseek to traverse through the file from start to end
and capturing the data into a linked list structure. However, my loop
doesn't seem to work well - it totally fumbles out actually:

while ((a = fseek(fp,0,SEEK_CUR)) == 0){
// code here
}

Its quite important for me not to disrupt the current position of the
cursor since I rely on that to fetch the data from the text file. I
thought that the loop would work fine since fseek only returns a
non-zero integer on an error but unfortunately this is not the case.
Anyone with suggestions with using fseek() or some other function?

Any help would be greatly appreciated! Thanks.

Of course, there is feof(fp) for these purposes.
 
C

Chris Torek

(The correct answer is "no", as I believe others have already
posted. Unix-like systems allow a quite simple demonstration: open
a file for both reading and writing, seek to a position many
gigabytes past the existing EOF, and write one byte. The file is
suddenly that much longer. [Note that modern Unix-like systems
support multi-terabyte files. Of course, you cannot use fseek()
to do this unless LONG_MAX is more than 2147483647, e.g., on Itanium
or Alpha.] Since you can seek to any location, including nonexistent
beyond-current-EOF locations, in order to extend a file, it
necessarily follows that seeks past the existing EOF do not fail
-- at least if the file is open for writing. As it happens, this
holds for read-only files as well.)

Of course, there is feof(fp) for these purposes.

feof(fp) is not "for those purposes". The feof() function has only
one purpose: after an attempt to read fails, feof() and ferror()
distinguish between the two possible reasons for such a failure: EOF,
or error.

The read failure *must* occur first, though.
 
L

lawrence.jones

Karthiik Kumar said:
Of course, there is feof(fp) for these purposes.

No, there isn't. feof() doesn't tell you if trying to read *will*
return EOF, it only tells you if a previous read *already returned* EOF.

-Larry Jones

I've never seen a sled catch fire before. -- Hobbes
 
A

Anand

Orion said:
Hey,

I was wondering if it was possible to determine if you hit 'EOF' using
fseek? I'm using fseek to traverse through the file from start to end
and capturing the data into a linked list structure. However, my loop
doesn't seem to work well - it totally fumbles out actually:

while ((a = fseek(fp,0,SEEK_CUR)) == 0){
// code here
}

Its quite important for me not to disrupt the current position of the
cursor since I rely on that to fetch the data from the text file. I
thought that the loop would work fine since fseek only returns a
non-zero integer on an error but unfortunately this is not the case.
Anyone with suggestions with using fseek() or some other function?

Any help would be greatly appreciated! Thanks.



Hi

To read all characters from a text file upto EOF better u can go
for feof
function. Iam giving an example so that u can understand

Method1:

FILE *Fp;
int ch;

Fp=fopen("c:\\test.txt","rb");

while((ch=fgetc(Fp))!=EOF)
printf("%c",ch);

fclose(Fp);

Method2:

File *Fp;
char ch;

Fp=fopen("c:\\test.txt","rb");

ch=fgetc(Fp);

while(!feof(Fp))
{

printf("%c",ch);
ch=fgetc(Fp);
}

fclose(Fp);

The above two methods will work correctly. The reason EOF value is
FFFF.
It will go beyond the range. so normally an unsigned char cannot able
to hold the value of EOF. So u can get an logical error while reading
entire file becus
fgetc will treat EOF as character. Hope these ideas will make u
clear.

regards,

Anand.
 
C

Chris Torek

To read all characters from a text file upto EOF better u can go
for feof function.

This is not a good idea.
[snipped -- it should work, although it seems peculiar to fopen()
a file named "test.txt" with "rb" -- binary -- mode.]
Method2:

File *Fp;
char ch;

Fp=fopen("c:\\test.txt","rb");

ch=fgetc(Fp);

while(!feof(Fp))
{

printf("%c",ch);
ch=fgetc(Fp);
}

fclose(Fp);

The above two methods will work correctly.

The second method could loop forever if run on an input file that
is (e.g.) on a bad floppy disk. (Remember floppies? :) ) Suppose
fgetc() attempts to read a sector off the floppy, but the sector
is bad. The read will fail, but *not* because of end-of-file.
The C standard then suggests that feof(Fp) should return 0, and
ferror(Fp) should return some nonzero value. This is indeed what
happens on some real systems.
The reason EOF value is FFFF.

Actually, EOF is a macro "#define"d in <stdio.h> to some negative
integral value (often just -1, but any negative integral value is
allowed).
It will go beyond the range. so normally an unsigned char cannot able
to hold the value of EOF.

The value EOF expands to may or may not be outside the range of a
plain (and thus possibly signed) "char". It is indeed outside the
range of an unsigned char, and if EOF is #defined to -1, the result
of:

unsigned char uc = EOF;

is to set uc to UCHAR_MAX, by definition. But this is rarely 0xffff;
more commonly, this is 0xff.

As a rule, if you ever see a "while (!feof(...))" loop in C, the
code is going to be wrong. The only place you should normally see
feof() or ferror() calls is inside an "if (...)". One can construct
exceptions to this rule, but in real code, it works pretty well:
be very suspicious of any loop controlled by an feof() call.
 
R

RCollins

Chris said:
To read all characters from a text file upto EOF better u can go
for feof function.


This is not a good idea.


[snipped -- it should work, although it seems peculiar to fopen()
a file named "test.txt" with "rb" -- binary -- mode.]

Method2:

File *Fp;
char ch;

Fp=fopen("c:\\test.txt","rb");

ch=fgetc(Fp);

while(!feof(Fp))
{

printf("%c",ch);
ch=fgetc(Fp);
}

fclose(Fp);

The above two methods will work correctly.


The second method could loop forever if run on an input file that
is (e.g.) on a bad floppy disk. (Remember floppies? :) ) Suppose
fgetc() attempts to read a sector off the floppy, but the sector
is bad. The read will fail, but *not* because of end-of-file.
The C standard then suggests that feof(Fp) should return 0, and
ferror(Fp) should return some nonzero value. This is indeed what
happens on some real systems.[/QUOTE]

OK, you lost me here. I would think that if the source file or media
is corrupt, that *nothing* in C would be guaranteed to work correctly.
Why would one method (at the C level) work better than another?
Actually, EOF is a macro "#define"d in <stdio.h> to some negative
integral value (often just -1, but any negative integral value is
allowed).




The value EOF expands to may or may not be outside the range of a
plain (and thus possibly signed) "char". It is indeed outside the
range of an unsigned char, and if EOF is #defined to -1, the result
of:

unsigned char uc = EOF;

is to set uc to UCHAR_MAX, by definition. But this is rarely 0xffff;
more commonly, this is 0xff.

As a rule, if you ever see a "while (!feof(...))" loop in C, the
code is going to be wrong. The only place you should normally see
feof() or ferror() calls is inside an "if (...)". One can construct
exceptions to this rule, but in real code, it works pretty well:
be very suspicious of any loop controlled by an feof() call.

Again, I don't follow your reasoning. The "if (something)" and
"while (something)" constructs both expect "something" to be a logical
expression (evaluates either to 0 or non-0). Why is "if (feof(...))"
better than "while (feof(...))" ?
 
J

Joe Wright

RCollins said:
Chris said:
To read all characters from a text file upto EOF better u can go
for feof function.



This is not a good idea.



[snipped -- it should work, although it seems peculiar to fopen()
a file named "test.txt" with "rb" -- binary -- mode.]

Method2:

File *Fp;
char ch;

Fp=fopen("c:\\test.txt","rb");

ch=fgetc(Fp);

while(!feof(Fp))
{

printf("%c",ch);
ch=fgetc(Fp); }

fclose(Fp);

The above two methods will work correctly.



The second method could loop forever if run on an input file that
is (e.g.) on a bad floppy disk. (Remember floppies? :) ) Suppose
fgetc() attempts to read a sector off the floppy, but the sector
is bad. The read will fail, but *not* because of end-of-file.
The C standard then suggests that feof(Fp) should return 0, and
ferror(Fp) should return some nonzero value. This is indeed what
happens on some real systems.


OK, you lost me here. I would think that if the source file or media
is corrupt, that *nothing* in C would be guaranteed to work correctly.
Why would one method (at the C level) work better than another?
Actually, EOF is a macro "#define"d in <stdio.h> to some negative
integral value (often just -1, but any negative integral value is
allowed).





The value EOF expands to may or may not be outside the range of a
plain (and thus possibly signed) "char". It is indeed outside the
range of an unsigned char, and if EOF is #defined to -1, the result
of:

unsigned char uc = EOF;

is to set uc to UCHAR_MAX, by definition. But this is rarely 0xffff;
more commonly, this is 0xff.

As a rule, if you ever see a "while (!feof(...))" loop in C, the
code is going to be wrong. The only place you should normally see
feof() or ferror() calls is inside an "if (...)". One can construct
exceptions to this rule, but in real code, it works pretty well:
be very suspicious of any loop controlled by an feof() call.


Again, I don't follow your reasoning. The "if (something)" and
"while (something)" constructs both expect "something" to be a logical
expression (evaluates either to 0 or non-0). Why is "if (feof(...))"
better than "while (feof(...))" ?
[/QUOTE]

The canonical method for reading a file to the end is..
int c;
FILE *in;
....
while ((c = fgetc(in)) != EOF) {

}
Now when fgetc() detects EOF it is before the loop executes for that
character. After the loop test "if (!feof(in)) {}" to know whether
EOF meant end-of-file or was an error.

If the control was "while (!feof(...))" with "c = fgetc(in)" inside
the loop, the loop is executed with c == EOF which is probably not
what you want.
 
C

Chris Torek

OK, you lost me here. I would think that if the source file or media
is corrupt, that *nothing* in C would be guaranteed to work correctly.

The source file is fine. The media from which the C programs are
run (local "hard drives", for instance) are also fine. The *input
file*, however, is on a bad floppy (or similar corrupt medium).

(Of course, we can postulate a single bad sector in the middle of
a data file on a "hard drive" -- incidentally, having been using
systems long before the PC popularized the silly phrase "hard
drive", I happen to find it annoying :) -- with the rest of the
disk being OK. This results in the same problem. But I think it
may be easier to envision "good local disk, bad floppy".)
Why would one method (at the C level) work better than another?

The fgetc() call fails and returns EOF. Why? Is the reason for
the EOF return "because the attempt to read from the input file is
about to go past the known end-point of the file", or is it "because
the attempt to read from the input file failed even though we know
for sure we have not yet reached EOF"?

If the file system format on the floppy is such that the bad spot
does not affect the system's sure-ness of the original file size
-- i.e., if the file has some associated "metadata" that is still
readable and valid, so that we know the original input file should
be (say) 27812 bytes long -- and the error occurs when reading the
third sector (bytes 1024 through 1535 inclusive), the substrate
underlying the C system's standard I/O *should* report this as
"error reading file" (ferror(fp) becomes true) rather than "reached
end of file" (feof(fp) becomes true). The loop that tests for
feof(fp) will then run forever, attempting to read sector three
of the file again and again and again and again and again....
Again, I don't follow your reasoning. The "if (something)" and
"while (something)" constructs both expect "something" to be a logical
expression (evaluates either to 0 or non-0). Why is "if (feof(...))"
better than "while (feof(...))" ?

Pretty much for the same reason a biological-analysis program that
reads:

while (is_dead(subject_under_test))
do_some_stuff(subject_under_test);

would be wrong: the subject is not going to spring to life again.[%]
Similarly, files do not normally suddenly become longer (so that
feof(fp) changes from "true" -- nonzero -- to zero), nor do they
normally have uncorrectable errors magically correct themselves
(so that ferror(fp) changes from nonzero to zero). Thus, it does
not make sense to repeat the test.
[% Dr Frankenstein's lab excepted, of course]

As I also said, there are exceptions (such as "tail -f" in the
Unix/POSIX world), but if you are using stdio, you must also use
the clearerr() function. Such exceptions will become obvious upon
the close scrutiny you should give a function that has an EOF or
error test as the controlling part of a "while" loop.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top