problem using fread, fwrite, and fsetpos

B

Brady

Hi,

I'm having a problem reading and writing to a file. What I'm trying
to do is read a file, modify the portion of the file that I just read,
and then write the modified data back to the same location in the
file.

What is happening, is I can read the file, either in entirety or only
part of it. And no matter what I try setting the position to, using
fsetpos, it always gets set back to the very beginning of the file. I
wrote sample code which demonstrates this.

#include <stdio.h>

int main()
{
FILE* input= fopen("test.dat", "rb+");

int read = 0;
while(!feof(input))
{
fread(&read, sizeof(int), 1, input);
}

fpos_t pos = 10; /* some random location in the file, 10 used as
example */
fsetpos(input, &pos);

int temp = 3;
fwrite(&temp, sizeof(int), 1, input);
fclose(input);
return 0;
}

When I call fsetpos(input, &pos), I am watching the values of the
FILE*, input. No matter what the value of pos is, the _ptr member of
input, gets set to the same value of _base.

I've read the posts saying you need to use an fsetpos, rewind, or
fseek, to change from read or write back into undetermined mode, and I
don't see why I'm having this problem.

Any help would be greatly appreciated. This problem has been plaguing
me for the last week.

Thanks,
Bryan
 
S

Sven Gohlke

Brady said:
I'm having a problem reading and writing to a file. What I'm trying
to do is read a file, modify the portion of the file that I just read,
and then write the modified data back to the same location in the
file.
[...]

fpos_t pos = 10; /* some random location in the file, 10 used as
example */

And here I get an error: "Invalid initializer". Unlike fseek(), fsetpos()
don't use long as the second parameter but a struct. Either You use fseek
(input, pos, SEEK_SET) (with pos as long, not fpos_t) or You write 10
characters, call fgetpos (input, &pos) and write the rest. Then You can use
pos with fsetpos().
 
R

Richard Bos

#include <stdio.h>

int main()
{
FILE* input= fopen("test.dat", "rb+");

int read = 0;
while(!feof(input))

This is not the right way to read a file. Read the FAQ:
{
fread(&read, sizeof(int), 1, input);
}

fpos_t pos = 10; /* some random location in the file, 10 used as
example */
fsetpos(input, &pos);

From the latest public draft of the Standard:

[#2] The fsetpos function sets the mbstate_t object (if any)
and file position indicator for the stream pointed to by
stream according to the value of the object pointed to by
pos, which shall be a value obtained from an earlier
successful call to the fgetpos function on a stream
associated with the same file.

Note the last clause. You cannot just pass a random number to fsetpos().
In fact, fpos_t isn't even required to be any kind of scalar, so
assigning 10 to it is not legal. You need to get your position from
fgetpos() itself, otherwise fsetpos() isn't required to work.

Richard
 
R

Richard Bos

Sven Gohlke said:
And here I get an error: "Invalid initializer". Unlike fseek(), fsetpos()
don't use long as the second parameter but a struct.

Not necessarily. You cannot rely on it being a long _or_ a struct. It's
an fpos_t; and that's all you know it is.

Richard
 
A

Anaz

Hi
The fsetpos function sets the file-position indicator for stream to
the value of pos, which is obtained in a prior call to fgetpos against
stream.
So you have to use fgetpos aprior to fsetpos.

see a sample code given below.
Regards
[Anaz K Kabeer]

* FGETPOS.C: This program opens a file and reads
* bytes at several different locations.
*/

#include <stdio.h>

void main( void )
{
FILE *stream;
fpos_t pos;
char buffer[20];

if( (stream = fopen( "fgetpos.c", "rb" )) == NULL )
printf( "Trouble opening file\n" );
else
{
/* Read some data and then check the position. */
fread( buffer, sizeof( char ), 10, stream );
if( fgetpos( stream, &pos ) != 0 )
perror( "fgetpos error" );
else
{
fread( buffer, sizeof( char ), 10, stream );
printf( "10 bytes at byte %ld: %.10s\n", pos, buffer );
}

/* Set a new position and read more data */
pos = 140;
if( fsetpos( stream, &pos ) != 0 )
perror( "fsetpos error" );

fread( buffer, sizeof( char ), 10, stream );
printf( "10 bytes at byte %ld: %.10s\n", pos, buffer );
fclose( stream );
}
}
 
A

Al Bowers

Brady said:
Hi,

I'm having a problem reading and writing to a file. What I'm trying
to do is read a file, modify the portion of the file that I just read,
and then write the modified data back to the same location in the
file.

What is happening, is I can read the file, either in entirety or only
part of it. And no matter what I try setting the position to, using
fsetpos, it always gets set back to the very beginning of the file. I
wrote sample code which demonstrates this.

#include <stdio.h>

int main()
{
FILE* input= fopen("test.dat", "rb+");

int read = 0;
while(!feof(input))
{
fread(&read, sizeof(int), 1, input);
}

fpos_t pos = 10; /* some random location in the file, 10 used as
example */
fsetpos(input, &pos);

int temp = 3;
fwrite(&temp, sizeof(int), 1, input);
fclose(input);
return 0;
}

When I call fsetpos(input, &pos), I am watching the values of the
FILE*, input. No matter what the value of pos is, the _ptr member of
input, gets set to the same value of _base.

I've read the posts saying you need to use an fsetpos, rewind, or
fseek, to change from read or write back into undetermined mode, and I
don't see why I'm having this problem.

Any help would be greatly appreciated. This problem has been plaguing
me for the last week.

How do you know that the file was opened or that any of the positioning
attemps were successful. You need to check the return values of these
functions.

/* test.c
change in file element 3 in an int array from 3 to 99 */

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
FILE* input= fopen("tes.dat", "w+b");
int array[10] = {0,1,2,3,4,5,6,7,8,9};
fpos_t pos,offset;
int temp = 99;

if(input == NULL)
{
perror("Unable to open the file");
exit(EXIT_FAILURE);
}
printf("Before changing file: array[3] = %d\n",array[3]);
if(1 != fwrite(array,sizeof array,1,input))
{
perror("Unable to write to file test.dat");
exit(EXIT_FAILURE);
}
rewind(input);
if(1 != fread(array,sizeof(int),1,input))
{
perror("Unable to read to file test.dat");
exit(EXIT_FAILURE);
}
if(0 != fgetpos(input,&offset))
{
perror("Error with fgetpos function");
exit(EXIT_FAILURE);
}
printf("offset = %lu\n",offset);
pos = offset*3; /* positions at array[3] */
if(0 != fsetpos(input,&pos))
{
perror("Error with fsetpos function");
exit(EXIT_FAILURE);
}
/* modify element 3 in the file.*/
if(1 != fwrite(&temp,sizeof temp, 1, input))
{
perror("Error writing to the file");
exit(EXIT_FAILURE);
}
rewind(input);
if(1 != fread(array,sizeof array,1,input))
{
perror("Read error reading array");
exit(EXIT_FAILURE);
}
printf("After changing file: array[3] = %d\n",array[3]);
fclose(input);
return 0;
}
 
G

goose

Hi,

I'm having a problem reading and writing to a file. What I'm trying
to do is read a file, modify the portion of the file that I just read,
and then write the modified data back to the same location in the
file.

What is happening, is I can read the file, either in entirety or only
part of it. And no matter what I try setting the position to, using
fsetpos, it always gets set back to the very beginning of the file. I
wrote sample code which demonstrates this.

#include <stdio.h>

int main()
{
FILE* input= fopen("test.dat", "rb+");

int read = 0;

you forget to check that you opened the file successfully.
while(!feof(input))
{
fread(&read, sizeof(int), 1, input);
}

fpos_t pos = 10; /* some random location in the file, 10 used as
example */

unless you are using a c99 compiler, you cant mix variable
declarations and code.

also, according to the documentation on my system, fpos_t *may*
not be an int, as you assigned it.
fsetpos(input, &pos);

(from my man pages)

#include <stdio.h>
int fsetpos(FILE *FP, const fpos_t *POS);
(...)
You can use `fsetpos' to return the file identified by
FP to a previous position `*POS' (after first recording it
with `fgetpos').


(and from the same page)
ANSI C requires `fsetpos', but does not specify the nature
of `*POS' beyond identifying it as written by `fgetpos'.

this means that the second argument to fsetpos() *must* be of type
fpos_t, which can *only* be returned by fgetpos().

What you should do is use fgetpos() to store a value into the fpos_t
variable.

replace
pos = 10;

with
fseek (input, 10, SEEK_SET);
fgetpos (input, &pos);

also dont forget to check the return values of the functions. they
may be trying to tell you that (for example) you are setting an invalid
position in the file.
int temp = 3;
fwrite(&temp, sizeof(int), 1, input);
fclose(input);
return 0;
}

When I call fsetpos(input, &pos), I am watching the values of the
FILE*, input. No matter what the value of pos is, the _ptr member of
^^^^
there isn't any need to do this, just check the return values, and
remember that fpos_t may not be an integer.
input, gets set to the same value of _base.

I've read the posts saying you need to use an fsetpos, rewind, or
fseek, to change from read or write back into undetermined mode, and I

I have no idea what you are trying to say here. what is "undetermined
mode" ?

hth
goose,
 
D

Dan Pop

In said:
Not necessarily. You cannot rely on it being a long _or_ a struct. It's
an fpos_t; and that's all you know it is.

You also know what it cannot be: an array.

Dan
 
D

Dave Thompson

I'm having a problem reading and writing to a file. <snip>
What is happening, is I can read the file, either in entirety or only
part of it. And no matter what I try setting the position to, using
fsetpos, it always gets set back to the very beginning of the file. I
wrote sample code which demonstrates this. <snip>
When I call fsetpos(input, &pos), I am watching the values of the
FILE*, input. No matter what the value of pos is, the _ptr member of
input, gets set to the same value of _base.
In addition to the correct comments elsethread that fpos_t need not be
an integer type nor linear bytes even if it is and about feof(), even
if your call to fsetpos() actually worked, or if you used instead
fseek(pos,SEEK_SET) which would work on a binary stream,
there is no reason to expect that the file position appears in the
FILE structure, whose contents are implemention-defined; on many,
perhaps most, operating systems it is handled entirely in the OS.

_ptr and _base on your implementation almost certainly refer to the
currently used/valid portion of the in-memory buffer, and after any
positioning call that buffer normally should be reset.


- David.Thompson1 at worldnet.att.net
 

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

fread/fwrite 2 18
H&S fread/fwrite 7
fread fwrite struct 4
fwrite() fails when called after fread() 2
fread() 2
fwrite, fgets binary file readback problem 16
Understanding fwrite() 10
another fwrite() problem 4

Members online

Forum statistics

Threads
473,769
Messages
2,569,577
Members
45,052
Latest member
LucyCarper

Latest Threads

Top