fseek

B

Bill Cunningham

This seems like a simple enough question that it shouldn't be too difficultin clc discussion. If the discussion would turn to learning or teaching. Iwant to allocate enough memory to hold a whole file. malloc is of course going to be needed so I think fseek is the way to learn how big a file is. Itried this and the code compiled find and displayed nothing so I'm at a loss as to what happened. I deleted the source code so I will make referencesto it.

#include <stdio.h>

FILE *fp;
if ((fp=fopen("j","rb"))==NULL)
perror("fopen 1 error");
long l;
while(!feof(fp))
l=fseek(fp,0,SEEK_SET);
fclose(fp);
printf("%d\n%d\n",l,ftell(fp));
}

This compiles fine and prints nothing. Did the file pointer move? Or is there a problem with printf?

Bill
 
C

cartec69

l=fseek(fp,0,SEEK_SET);

You are instructing the file (fp) to seek to a position 0 bytes away from the
current position (SEEK_SET). It's effectively a no-op that returns the current file position, which will always be zero since you've just opened the file and done nothing with it. If the file size is non-zero, the while loop will never terminate.
 
L

Les Cargill

Bill said:
This seems like a simple enough question that it shouldn't be too difficult in clc discussion. If the discussion would turn to learning or teaching. I want to allocate enough memory to hold a whole file. malloc is of course going to be needed so I think fseek is the way to learn how big a file is. I tried this and the code compiled find and displayed nothing so I'm at a loss as to what happened. I deleted the source code so I will make references to it.

#include <stdio.h>

FILE *fp;
if ((fp=fopen("j","rb"))==NULL)
perror("fopen 1 error");
long l;

You don't really need the eof check
nor the "while..." Just call fseek().
while(!feof(fp))
l=fseek(fp,0,SEEK_SET);

you're close. Try
l=fseek(fp,0,SEEK_END);

That will at least get you to the next bug.

And can I buy you some indentation? :) Good
habit to develop.
fclose(fp);

Closing a file and then calling eof is at the
very least bad form.
printf("%d\n%d\n",l,ftell(fp));
}

This compiles fine and prints nothing. Did the file pointer move? Or is there a problem with printf?

Bill

#include <stdio.h>
#include <assert.h>

int main(void)
{
FILE *fp;
fp=fopen("j","rb");
assert(fp);

long l = fseek(fp,0L,SEEK_END);
assert(l==0);

printf("l=%d\nFile size is %d\n",l,ftell(fp));

fclose(fp);

return 1;
}
 
L

Les Cargill

You are instructing the file (fp) to seek to a position 0 bytes away
from the current position (SEEK_SET).


SEET_SET is relative to the beginning of the file. SEEK_CUR is relative
to the current position. SEEK_END is relative to the end.

It's effectively a no-op that
returns the current file position, which will always be zero since
you've just opened the file and done nothing with it. If the file
size is non-zero, the while loop will never terminate.

That's true.
 
J

James Kuyper

On 07/27/2012 12:13 AM, Les Cargill wrote:
....
#include <stdio.h>
#include <assert.h>

int main(void)
{
FILE *fp;
fp=fopen("j","rb");
assert(fp);

long l = fseek(fp,0L,SEEK_END);

While that will often do precisely what you're expecting it to do, "A
binary stream need not meaningfully support fseek calls with a whence
value of SEEK_END." (7.21.9.2p3)
 
L

Les Cargill

James said:
On 07/27/2012 12:13 AM, Les Cargill wrote:
...

While that will often do precisely what you're expecting it to do, "A
binary stream need not meaningfully support fseek calls with a whence
value of SEEK_END." (7.21.9.2p3)

Wow - didn't know that. Thanks! Hopefully, it returns a nonzero
when it does not apply to that stream.
 
K

Keith Thompson

Les Cargill said:
James Kuyper wrote:

Not necessarily.

N1570 7.21.2p3:

A binary stream is an ordered sequence of characters that can
transparently record internal data. Data read in from a binary
stream shall compare equal to the data that were earlier written
out to that stream, under the same implementation. Such a stream
may, however, have an implementation-defined number of null
characters appended to the end of the stream.

For example, a system might only support binary files consisting of a
whole number of fixed-size blocks.
 
K

Keith Thompson

Keith Thompson said:
Not necessarily.

N1570 7.21.2p3:

A binary stream is an ordered sequence of characters that can
transparently record internal data. Data read in from a binary
stream shall compare equal to the data that were earlier written
out to that stream, under the same implementation. Such a stream
may, however, have an implementation-defined number of null
characters appended to the end of the stream.

For example, a system might only support binary files consisting of a
whole number of fixed-size blocks.

Whoops, I goofed when trimming the quoted text. Here's the context I
*meant* to quote:

Les Cargill said:
James Kuyper wrote: [...]
While that will often do precisely what you're expecting it to do, "A
binary stream need not meaningfully support fseek calls with a whence
value of SEEK_END." (7.21.9.2p3)

Wow - didn't know that. Thanks! Hopefully, it returns a nonzero
when it does not apply to that stream.

....
 
L

Les Cargill

Keith said:
Keith Thompson said:
Not necessarily.

N1570 7.21.2p3:

A binary stream is an ordered sequence of characters that can
transparently record internal data. Data read in from a binary
stream shall compare equal to the data that were earlier written
out to that stream, under the same implementation. Such a stream
may, however, have an implementation-defined number of null
characters appended to the end of the stream.

For example, a system might only support binary files consisting of a
whole number of fixed-size blocks.

Whoops, I goofed when trimming the quoted text. Here's the context I
*meant* to quote:

Les Cargill said:
James Kuyper wrote: [...]
While that will often do precisely what you're expecting it to do, "A
binary stream need not meaningfully support fseek calls with a whence
value of SEEK_END." (7.21.9.2p3)

Wow - didn't know that. Thanks! Hopefully, it returns a nonzero
when it does not apply to that stream.

...

James, I have been programming in 'C'... perhaps longer than
I should have, and I have never come across a device that would not
feeek(...,SEEK_END) exactly as one would expect it would.

I remember nine-track tape too, but I wasn't doing *that* in 'C'.

Yadda, yadda, etc, esp ipsioders infinitum. :)

:)

(it even works on USB! Sacre mirablieu!!)
 
J

James Kuyper

Keith said:
Keith Thompson said:
James Kuyper wrote:

Not necessarily.

N1570 7.21.2p3:

A binary stream is an ordered sequence of characters that can
transparently record internal data. Data read in from a binary
stream shall compare equal to the data that were earlier written
out to that stream, under the same implementation. Such a stream
may, however, have an implementation-defined number of null
characters appended to the end of the stream.

For example, a system might only support binary files consisting of a
whole number of fixed-size blocks.

Whoops, I goofed when trimming the quoted text. Here's the context I
*meant* to quote:

Les Cargill said:
James Kuyper wrote: [...]
While that will often do precisely what you're expecting it to do, "A
binary stream need not meaningfully support fseek calls with a whence
value of SEEK_END." (7.21.9.2p3)


Wow - didn't know that. Thanks! Hopefully, it returns a nonzero
when it does not apply to that stream.

...

James, I have been programming in 'C'... perhaps longer than
I should have, and I have never come across a device that would not
feeek(...,SEEK_END) exactly as one would expect it would.

As I said, "that will often do precisely what you're expecting it to
do.". I didn't say how often, because I have no idea. I write my code to
avoid relying upon anything that isn't guaranteed by the applicable
standards, rather than trying to keep track of how common it is for the
unguaranteed behavior to be what I might otherwise expect it to be.

On my current project, where I've been working since 1996, the
applicable standards are C90 plus the corresponding TCs, and a
comparably out-dated version of POSIX, plus some project-specific
standards that wouldn't be meaningful to you. I believe that POSIX does
guarantee the behavior, at least when stream represents an actual file,
rather than a device - but this group isn't about POSIX. stat() would be
the more direct way of obtaining the same information, but it's use is
prohibited by the project-specific standards mentioned above.
 
B

Ben Bacarisse

Les Cargill said:
James, I have been programming in 'C'... perhaps longer than
I should have, and I have never come across a device that would not
feeek(...,SEEK_END) exactly as one would expect it would.

Well, the "exactly as one would expect" makes the statement entirely
dependent on what one expects! But for people with less experienced
expectations, surprises are certainly possible. For example, fseek(...,
SEEK_END) on an open FIFO will fail and there are other special files
(at least on Linux) that are not seekable.

Of course that's just things that you can't seek on. Other surprises
include readable files (like /dev/zero) where seeking to the end gives a
position of 0. You can seek -1000 bytes back from the end if you like
and you'll be still at file position 0.

And some people are surprised that you can seek beyond the end of plain
file, even when it is opened only for reading.
 
L

Les Cargill

Ben said:
Well, the "exactly as one would expect" makes the statement entirely
dependent on what one expects! But for people with less experienced
expectations, surprises are certainly possible. For example, fseek(...,
SEEK_END) on an open FIFO will fail and there are other special files
(at least on Linux) that are not seekable.

Well, sure. But other than the sort of experimental learning we
all do with a new system, there's probably not a compelling reason
to call fseek() on a FIFO :)
 
B

Ben Bacarisse

Les Cargill said:
Well, sure. But other than the sort of experimental learning we
all do with a new system, there's probably not a compelling reason
to call fseek() on a FIFO :)

But code will often seek a file (either given by name or one already
open) with no idea what it is. When you use fseek in a program (and
more so in a reusable function like read_whole_file) you are, in effect,
making a compelling reason to call it on a FIFO because you can bet your
users will do so eventually.

If the OP decides that reading a whole file is best done with fseek,
ftell and big a fread, then it won't work on some things (like FIFOs).
Reading in chunks, and grow a buffer as you do so, will work on almost
any file at the expense of some cost in allocations. For many cases,
though, the file will be read in one or maybe two mouthfuls.

<snip>
 
L

Les Cargill

Ben said:
But code will often seek a file (either given by name or one already
open) with no idea what it is. When you use fseek in a program (and
more so in a reusable function like read_whole_file) you are, in effect,
making a compelling reason to call it on a FIFO because you can bet your
users will do so eventually.

Hence the idiom:
long l = fseek(fp,0L,SEEK_END);
assert(l==0);


It's a "toy" program or you'd need to do better cleanup than simply
assert()-ing out.
If the OP decides that reading a whole file is best done with fseek,
ftell and big a fread, then it won't work on some things (like FIFOs).

File size isn't a defined quantity for FIFOs.
Reading in chunks, and grow a buffer as you do so, will work on almost
any file at the expense of some cost in allocations. For many cases,
though, the file will be read in one or maybe two mouthfuls.

These days, I take it in one gulp usually - on a PC. And whoever
said "use stat()" is probably correct.
 
B

Ben Bacarisse

Les Cargill said:
Hence the idiom:
long l = fseek(fp,0L,SEEK_END);
assert(l==0);

That's an odd idiom. I hope it is not as popular as the term "idiom"
suggests. Why the "long"? Why use assert to test for an ordinary
error? It seems all wrong to me.
It's a "toy" program or you'd need to do better cleanup than simply
assert()-ing out.

Even toy programs can get compiled with NDEBUG defined, so I'd advise
most strongly against error-checking using assert.
File size isn't a defined quantity for FIFOs.

No, and it's not that well-defined for plain files, either! Not only
can files change but, if it's a text file, what you read might not be
what's stored.

Though size seems to have become the issue, the original problem was
about storing the whole file, and that doesn't need the size up-front
(though it helps, which is why people do it despite the down-side).
These days, I take it in one gulp usually - on a PC. And whoever
said "use stat()" is probably correct.

If the code is to be portable between systems, and the file is a text
file, I'd be wary of any method that loses the line ending translation.
Of course stat may be the way to go for the OP, but I don't feel I have
enough information to make a sound choice.
 

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

Similar Threads


Members online

Forum statistics

Threads
473,961
Messages
2,570,131
Members
46,689
Latest member
liammiller

Latest Threads

Top