End of FILE* pointer is not equal to size of written data
Asked Answered
H

4

8

Very simply put, I have the following code snippet:

FILE* test = fopen("C:\\core.u", "w");
printf("Filepointer at: %d\n", ftell(test));
fwrite(data, size, 1, test);
printf("Written: %d bytes.\n", size);
fseek(test, 0, SEEK_END);
printf("Filepointer is now at %d.\n", ftell(test));
fclose(test);

and it outputs:

Filepointer at: 0
Written: 73105 bytes.
Filepointer is now at 74160.

Why is that? Why does the number of bytes written not match the file pointer?

Halfhour answered 28/9, 2008 at 2:20 Comment(1)
I recommend not to use NT style paths in fopen() arguments. Windows also supports POSIX paths, which are portable and don't require escaping '\'.Moonmoonbeam
G
19

Since you're opening the file in text mode, it will convert end-of-line markers, such as LF, into CR/LF.

This is likely if you're running on Windows (and you probably are, given that your file name starts with "c:\").

If you open the file in "wb" mode, I suspect you'll find the numbers are identical:

FILE* test = fopen("C:\\core.u", "wb");

The C99 standard has this to say in 7.19.5.3 The fopen function:

The argument mode points to a string. If the string is one of the following, the file is open in the indicated mode. Otherwise, the behaviour is undefined.

r open text file for reading
w truncate to zero length or create text file for writing
a append; open or create text file for writing at end-of-file
rb open binary file for reading
wb truncate to zero length or create binary file for writing
ab append; open or create binary file for writing at end-of-file
r+ open text file for update (reading and writing)
w+ truncate to zero length or create text file for update
a+ append; open or create text file for update, writing at end-of-file
r+b or rb+ open binary file for update (reading and writing)
w+b or wb+ truncate to zero length or create binary file for update
a+b or ab+ append; open or create binary file for update, writing at end-of-file

You can see they distinguish between w and wb. I don't believe an implementation is required to treat the two differently but it's usually safer to use binary mode for binary data.

Glazed answered 28/9, 2008 at 2:23 Comment(2)
This is a rather dark corner of the language, I'm afraid. One tends to not know it is there until they've been bitten by it. Nice catch!Weirick
It's worth noting that POSIX requires the implementation not to treat them differently.Guayule
A
0

what does fwrite return? normally the return value should be the number of bytes written. Also, what does the ftell() answer with right before the fseek?

It might help to know what operating system, C compiler version and C library.

Anatolia answered 29/9, 2008 at 4:26 Comment(0)
M
0

A filepointer is a cookie. It has no value. The only thing you can use it for is to seek to the same place in a file. I'm not even sure if ISO C guarantees that ftell returns increasing values. If you don't believe this, please look at the different seek() modes. They exist precisely because the position is not a simple byte offset.

Messick answered 29/9, 2008 at 12:32 Comment(6)
Yeah, but they have to be implemented somehow. Even if it's not specified by the standard, file pointers will simply be byte offsets in many implementations, so it's overly pedantic to say that it has "no value".Posture
It is not a cookie. It's a byte offset in binary mode. Text mode is hell and makes almost no guarantees about anything working at all, and simply should not be used.Guayule
@R.. : please quote the part of the C standard that guarantees so. Even the byte mode is a POSIX extension.Messick
No, the C standard defined both text mode (which is so implementation-defined that you can't rely on it doing anything useful) and binary mode (which is byte addressable and where each call to fputc (in terms of which all other write functions are defined) results in one byte ("char") being written and adjusts the file position by 1).Guayule
See 7.19.2 para 3 and 7.19.9.2 para 3.Guayule
Note that those talks about characters, not bytes. You'll also see 7.19.2/5 discuss Binary wide-oriented streams, and explicitly note that those have file-positioning restrictions. And 7.19.3/1 makes it explicit that it's optional whether a file position indicator even exists. But to augment my answer, I'm now sure that ftell does return increasing values.Messick
L
0

windows doesn't actually write all data out to the file without a flush and possibly an fsync. Maybe that's why

Lir answered 12/2, 2010 at 23:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.