File Seeking / Overwriting bytes

J

Jason

Hi,

I need to open an existing file, seek to a position at X number of
bytes, and write out Y number of bytes overwriting any existing bytes,
but no erasing any other data. Is this possible?

I've opened a file in append "a" mode, and then used fseek with
SEEK_SET to seek to 0 bytes into the file, but this sets the position
at the end of existing data, not actually at the start of the file.

So say I have a file of 8 bytes: 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
0xFF
I want to open it, seek to a specific offset, lets say 2 bytes in,
then write out 4 bytes with the value 1D overwriting existing bytes,
leaving the file with: 0xFF 0xFF 0x1D 0x1D 0x1D 0x1D 0xFF 0xFF

Heres my testing code.

FILE *cont;
cont = fopen("/home/jk/test.txt", "a");
fseek(cont, 0, SEEK_SET);
fputs("T", cont);
fclose(cont);


Please can someone point me in the right direction, I want to avoid
reading everything in, editing it and rewriting it all out because the
file could be huge.

Many thanks,
Jason
 
N

Nate Eldredge

Jason said:
Hi,

I need to open an existing file, seek to a position at X number of
bytes, and write out Y number of bytes overwriting any existing bytes,
but no erasing any other data. Is this possible?

I've opened a file in append "a" mode, and then used fseek with
SEEK_SET to seek to 0 bytes into the file, but this sets the position
at the end of existing data, not actually at the start of the file.

You want the "r+" mode.
 
A

Antoninus Twink

Ah that simple, thanks very much works perfectly.

You may also want to do an fsync() (or fclose() of course) after writing
the data, to make sure it gets committed to disk.
 
M

Martien Verbruggen

Try this..
fp = fopen(file, "r+");
fseek(fp, 11, SEEK_SET);
fputc('J', fp);
fclose(fp);

To remain portable, the second argument of fseek() has to be 0 or a value
returned by a previous call to ftell(). You should probably open the
file in binary mode.

Martien
 
K

Keith Thompson

Joe Wright said:
Jason said:
I need to open an existing file, seek to a position at X number of
bytes, and write out Y number of bytes overwriting any existing bytes,
but no erasing any other data. Is this possible?
[...]
Try this..

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

int main(void) {
FILE *fp;
char *file = "jc.txt";
int c;

fp = fopen(file, "w");
fprintf(fp, "My name is jason.\n");
fclose(fp);

fp = fopen(file, "r");
while ((c = getc(fp)) != EOF) putchar(c);
fclose(fp);

fp = fopen(file, "r+");
fseek(fp, 11, SEEK_SET);
fputc('J', fp);
fclose(fp);

fp = fopen(file, "r");
while ((c = getc(fp)) != EOF) putchar(c);
fclose(fp);

return 0;
}

I've left the testing of fopen(), etc. up to you.

You almost certainly want to do this in binary mode.
 
K

Keith Thompson

Joe Wright said:
Keith said:
Joe Wright said:
Jason wrote:
I need to open an existing file, seek to a position at X number of
bytes, and write out Y number of bytes overwriting any existing bytes,
but no erasing any other data. Is this possible? [...]
Try this..

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

int main(void) {
FILE *fp;
char *file = "jc.txt";
int c;

fp = fopen(file, "w");
fprintf(fp, "My name is jason.\n");
fclose(fp);

fp = fopen(file, "r");
while ((c = getc(fp)) != EOF) putchar(c);
fclose(fp);

fp = fopen(file, "r+");
fseek(fp, 11, SEEK_SET);
fputc('J', fp);
fclose(fp);

fp = fopen(file, "r");
while ((c = getc(fp)) != EOF) putchar(c);
fclose(fp);

return 0;
}

I've left the testing of fopen(), etc. up to you.
You almost certainly want to do this in binary mode.
It never occurred to me. Why on earth use binary mode?

For one thing, your fseek() call isn't guaranteed to be meaningful for
a text file; the behavior is undefined unless the offset is either
zero or a value obtained from an earlier call to ftell().

You'll probably get away with it if you (a) use fseek and ftell
carefully, and (b) avoid either overwriting or creating any new-lines,
but there could still be some issues.

On Unix-like systems, it doesn't make any difference; on Windows, a
new-line is represented as a two-character sequence, and other systems
have even stranger ways of representing lines in text files.
 
M

Martien Verbruggen

Joe said:
Keith said:
Try this..
[... see up-thread ...]

You almost certainly want to do this in binary mode.
It never occurred to me. Why on earth use binary mode?

To be sure the fseek() will work. On a text stream, you
can only fseek() to a position you've already recorded with
ftell(), or to the very beginning or the very end.

I don't think SEEK_END, which I assume you'd use to position at the end,
is supported on text streams.

C99: 7.19.9.2 - 4

4 For a text stream, either offset shall be zero, or offset shall be a
value returned by an earlier successful call to the ftell function on
a stream associated with the same file and whence shall be SEEK_SET.

I don't have a C90 standard, but a pre-standard draft has identical
wording to the above, so I assume the standard contains that wording as
well.

Martien
 
K

Keith Thompson

Martien Verbruggen said:
Joe said:
Keith Thompson wrote:
Try this..
[... see up-thread ...]

You almost certainly want to do this in binary mode.

It never occurred to me. Why on earth use binary mode?

To be sure the fseek() will work. On a text stream, you
can only fseek() to a position you've already recorded with
ftell(), or to the very beginning or the very end.

I don't think SEEK_END, which I assume you'd use to position at the end,
is supported on text streams.

C99: 7.19.9.2 - 4

4 For a text stream, either offset shall be zero, or offset shall be a
value returned by an earlier successful call to the ftell function on
a stream associated with the same file and whence shall be SEEK_SET.

I don't have a C90 standard, but a pre-standard draft has identical
wording to the above, so I assume the standard contains that wording as
well.

The wording you quoted implies that seeking to the end *is* allowed.
Valid calls are:

fseek(f, 0, SEEK_SET);
fseek(f, 0, SEEK_CUR);
fseek(f, 0, SEEK_END);
fseek(f, n, SEEK_SET);

where n was returned by a previous call to ftell() on the same file.
 
S

S M Ryan

Jason said:
Hi,

I need to open an existing file, seek to a position at X number of
bytes, and write out Y number of bytes overwriting any existing bytes,
but no erasing any other data. Is this possible?

In character mode it depends on the operating system. Unices will do what you
want, but it's not required that any system do so.
I've opened a file in append "a" mode, and then used fseek with
SEEK_SET to seek to 0 bytes into the file, but this sets the position
at the end of existing data, not actually at the start of the file.

That's what "a" mode does. It always writes at the end regardless of where the
file might be positioned. You need something like "w", "w+", or "r+".
Please can someone point me in the right direction, I want to avoid
reading everything in, editing it and rewriting it all out because the
file could be huge.

On modern systems that might actually be as cheap as anything else.
 
M

Martien Verbruggen

Martien Verbruggen said:
Joe Wright wrote:
Keith Thompson wrote:
Try this..
[... see up-thread ...]

You almost certainly want to do this in binary mode.

It never occurred to me. Why on earth use binary mode?

To be sure the fseek() will work. On a text stream, you
can only fseek() to a position you've already recorded with
ftell(), or to the very beginning or the very end.

I don't think SEEK_END, which I assume you'd use to position at the end,
is supported on text streams.

C99: 7.19.9.2 - 4

4 For a text stream, either offset shall be zero, or offset shall be a
value returned by an earlier successful call to the ftell function on
a stream associated with the same file and whence shall be SEEK_SET.

I don't have a C90 standard, but a pre-standard draft has identical
wording to the above, so I assume the standard contains that wording as
well.

The wording you quoted implies that seeking to the end *is* allowed.
Valid calls are:

fseek(f, 0, SEEK_SET);
fseek(f, 0, SEEK_CUR);
fseek(f, 0, SEEK_END);
fseek(f, n, SEEK_SET);

where n was returned by a previous call to ftell() on the same file.

I see... There are two possible readings there, depending on what
'whence shall be SEEK_SET' is linked to...

(offset == 0) or (offset == fseek value and whence == SEEK_SET)

or

(offset == 0 or offset == fseek value) and whence == SEEK_SET

In a programming language we heve precedence or grammar rules that tell
us which interpretation is the right one. English doesn't really ave
that. The presence or absence of a comma after 'and' IMO is not enough.

is there a ruling somewhere that makes clear which of these two
interpretations was the intended one? I find it har dto believe that
this hasn't popped up before 9and if it has, why wasn't it made less
ambiguous? Or am I the only one who thinks it is ambiguous?)


Martien
 
K

Keith Thompson

Martien Verbruggen said:
I see... There are two possible readings there, depending on what
'whence shall be SEEK_SET' is linked to...

(offset == 0) or (offset == fseek value and whence == SEEK_SET)

or

(offset == 0 or offset == fseek value) and whence == SEEK_SET

In a programming language we heve precedence or grammar rules that tell
us which interpretation is the right one. English doesn't really ave
that. The presence or absence of a comma after 'and' IMO is not enough.

is there a ruling somewhere that makes clear which of these two
interpretations was the intended one? I find it har dto believe that
this hasn't popped up before 9and if it has, why wasn't it made less
ambiguous? Or am I the only one who thinks it is ambiguous?)

I didn't find it ambiguous until you mentioned it. :cool:}

For the second interpretation, I think there would have to be a comma
after "the same file".
 
L

lawrence.jones

In regards to C99: 7.19.9.2p4:

For a text stream, either offset shall be zero, or offset shall
be a value returned by an earlier successful call to the ftell
function on a stream associated with the same file and whence
shall be SEEK_SET.

Keith Thompson said:
I didn't find it ambiguous until you mentioned it. :cool:}

For the second interpretation, I think there would have to be a comma
after "the same file".

And no comma after "offset shall be zero". Because English doesn't have
grouping operators, the standard is very carefully punctuated and also
makes judicious use of words like "either" and "both" to indicate the
correct parsing.
 
I

Ian Collins

In regards to C99: 7.19.9.2p4:

For a text stream, either offset shall be zero, or offset shall
be a value returned by an earlier successful call to the ftell
function on a stream associated with the same file and whence
shall be SEEK_SET.



And no comma after "offset shall be zero". Because English doesn't have
grouping operators, the standard is very carefully punctuated and also
makes judicious use of words like "either" and "both" to indicate the
correct parsing.

In non-American English commas are seldom, if ever, placed before an and.
 
I

Ian Collins

Richard said:
Ian Collins said:

I am not American, and I certainly don't use American English. Nevertheless
I often find myself using a comma immediately before an "and", and
sometimes afterwards as well(!), and none of my English teachers at school
ever objected, and this was in the days when most of the books I read were
written, and published, in the UK, and even those that did come from the
USA were "anglicised" (i.e. all the punctuation, grammar, and spelling was
translated back into English), and this, I hope, shows that my education
was not affected by US usage.

The above paragraph is obviously rather artificial, but it doesn't contain
any grammar that I would be unhappy using in my capacity as Englishman.
http://en.wikipedia.org/wiki/Serial_comma a fairly balanced account.
 
P

Phil Carmody

Ian Collins said:
In non-American English commas are seldom, if ever, placed before an and.

What about the Oxford comma? OUP and Fowler both recommend its use.
The Guardian's neutral, advising its use if it would aid understanding.
I'm a Brit, and I'm very pro the Oxford comma; this is surprising, as
I tend to disagree with Fowler practically every time he's used as
support for some contruct.

Phil
 
B

Ben Bacarisse

In regards to C99: 7.19.9.2p4:

For a text stream, either offset shall be zero, or offset shall
be a value returned by an earlier successful call to the ftell
function on a stream associated with the same file and whence
shall be SEEK_SET.



And no comma after "offset shall be zero". Because English doesn't have
grouping operators, the standard is very carefully punctuated and also
makes judicious use of words like "either" and "both" to indicate the
correct parsing.

To me, the most compelling argument is that if the other meaning were
intended the restriction on whence would surely come first: "For a
text stream, whence shall be SEEK_SET and either offset shall be zero
or offset shall be a value returned by a ...".

I think you can get rid of any trace of an alternate parse simply by
putting the whence restriction sooner:

For a text stream, either offset shall be zero, or whence shall be
SEEK_SET and offset shall be a value returned by an earlier
successful call to the ftell function on a stream associated with
the same file.

Now any attempt to make the "and offset shall be a value..." clause
apply to both parts of the preceding "or" results in a double
restriction on offset (it shall be zero and the result of ftell).
Readers naturally avoid such illogical parses.

I don't think the original is ambiguous, but it seems to have proved to
be so despite careful punctuation!
 
K

Keith Thompson

Ben Bacarisse said:
To me, the most compelling argument is that if the other meaning were
intended the restriction on whence would surely come first: "For a
text stream, whence shall be SEEK_SET and either offset shall be zero
or offset shall be a value returned by a ...".
[...]

Better yet, "For a text stream, whence shall be SEEK_SET and offset
shall be either zero or a value returned by a ...".

(And yes, I'd probably put a comma after SEEK_SET.)
 

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,954
Messages
2,570,116
Members
46,704
Latest member
BernadineF

Latest Threads

Top