Why is fwrite writing more than I tell it to?
Asked Answered
R

4

20
FILE *out=fopen64("text.txt","w+");
unsigned int write;
char *outbuf=new char[write];
//fill outbuf
printf("%i\n",ftello64(out));
fwrite(outbuf,sizeof(char),write,out);
printf("%i\n",write);
printf("%i\n",ftello64(out));

output:

0
25755
25868

what is going on? write is set to 25755, and I tell fwrite to write that many bytes to a file, which is at the beginning, and then im at a position besides 25755?

Rip answered 19/10, 2009 at 0:15 Comment(2)
As a side note, you should probably be using size_t for write instead of unsigned intHodgkins
And what's that new operator doing in the C language?Hodgkins
E
35

If you are on a DOSish system (say, Windows) and the file is not opened in binary mode, line-endings will be converted automatically and each "line" will add one byte.

So, specify "wb" as the mode rather than just "w" as @caf points out. It will have no effect on Unix like platforms and will do the right thing on others.

For example:

#include <stdio.h>

#define LF 0x0a

int main(void) {
    char x[] = { LF, LF };

    FILE *out = fopen("test", "w");

    printf("%d", ftell(out));
    fwrite(x, 1, sizeof(x), out);
    printf("%d", ftell(out));

    fclose(out);
    return 0;
}

With VC++:

C:\Temp> cl y.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.21022.08 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

y.c
Microsoft (R) Incremental Linker Version 9.00.21022.08
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:y.exe

C:\Temp> y.exe
04

With Cygwin gcc:

/cygdrive/c/Temp $ gcc y.c -o y.exe

/cygdrive/c/Temp $ ./y.exe
02
Employment answered 19/10, 2009 at 0:18 Comment(6)
...and you open in binary mode by using "wb" instead of "w" in fopen().Sales
Based on the OP's (slight) presence in the [mingw] and [cygwin] tags, I suspect this is the answer.Hodgkins
That's curious because cygwin setup asks which type of line endings to use (and recommends Unix style).Surfacetosurface
@Sinan - Yes, but MinGW will probably use the native line endings, thus causing slight confusion when switching between the two environments.Hodgkins
"Doing the right thing on others" is not the right way to think about it. DOS/CPM and UNIX just made different decisions in their architecture. DOS decided to separate the concept of carriage return and line feed while UNIX decided to merge the concepts just in the line feed character. The fact that there is no real difference between "wb" and "w" in UNIX means that you can't make "mysterious mistakes" with respect to opening and closing files in the "wrong mode". OTOH, DOS separates the concepts of line feed and carriage return which matches up with line printer semantics.Geraldo
It should be clear from the context that "the right thing" is platform-dependent and differ from one environment to another on the same computer.Surfacetosurface
G
4

It may depend on the mode in which you opened the file. If you open it as a text file, then \n may be written as \r\n in DOS/Windows systems. However, ftello64() probably only gives the binary file pointer, which would count in the extra \r characters written. Try clearing the outbuf[] of any \n data or try opening the out file as binary ("wb" instead of "w").

Geraldo answered 19/10, 2009 at 0:21 Comment(0)
H
2

The variable write is uninitialized and so the size of the array and the amount written will be essentially random.

Hintz answered 19/10, 2009 at 0:32 Comment(2)
I suspect it's initialized in the real code and the OP is just being overly-protective of posting production code on a public website.Hodgkins
Yes, after re-reading the question I agree this is not likely the cause of the original problem - I think Sinan's answer is probably right. But just in case it is a direct copy of the original code, I'll leave my answer here.Hintz
S
0

Interesting. Works fine on Windows VC++, albeit ftello64 replaced with ftell.

Sangsanger answered 19/10, 2009 at 0:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.