c language : fwrite doesnt do anything - c

{
FILE* f1 = fopen("C:\\num1.bin", "wb+");//it will create a new file
int A[] = { 1,3,6,28 }; //int arr
fwrite(A, sizeof(A), 1, f1); //should insert the A array to the file
}
I do see the file but even after the fwrite, the file remains empty (0 bytes), does anyone know why?

You need to close the file with fclose
Otherwise the write buffer will not (necessarily) force the file contents to be written to disk

A couple of things:
As #Grantly correctly noted above, you are missing a call to fclose or fflush after writing to the file. Without this any cached/pending writes will not necessarily be actually written to the open file.
You do not check the return value of fopen. If fopen fails for any reason it will return a NULL pointer and not a valid file pointer. Since you're writing directly to the root of the drive C:\ on a Windows platform, that's something you definitely do want to be checking for (not that you shouldn't in other cases too, but run under a regular user account that location is often write protected).

Result of fwrite is not required to appear in the fille immediately after it returns. That is because file operations usually work in a buffered manner, i.e. they are cached and then flushed to speed things up and improve the performance.
The content of the file will be updated after you call fclose:
fclose()
(...) Any unwritten buffered data are flushed to the OS. Any unread buffered
data are discarded.
You may also explicitly flush the internal buffer without closing the file using fflush:
fflush()
For output streams (and for update streams on which the last operation
was output), writes any unwritten data from the stream's buffer to the
associated output device.

Related

How do the fwrite() and fread() work when i open a binary file

I am learning C and I don't understand the fwrite() and fread().
double n;
FILE *p;
p = fopen("output.dat","w+b");
rewind(p);
fread(&n,sizeof(double),1,p);
printf("%lf",n);
n = 12.0;
fwrite(&n,sizeof(double),1,p);
fclose(p);
return 0;
It can't read and write the data as expected, why please
Take a moment to examine the table of modes in the documentation for fopen.
You'll see that the w+ mode will create a new file if one doesn't exist, or destroy the contents if the file exists.
So, after your call to fopen, you are guaranteed to have an empty file. The next thing you attempt to do is read data from it, which of course will fail. Your program has bogus output (undefined behavior) because you don't even test whether the operation succeeded and you output an uninintialized value.
Perhaps what you were wanting is to use the a+b open mode. That's evident by the fact you immediately call rewind. Of course, you still need to deal with the failed call to fread when this file is first created.

Why the restrictions on C standard I/O streams that interact with sockets?

In book CSAPP section 10.9, it says that there are two restrictions on standard I/O streams that interact badly with restrictions on sockets.
Restriction 1: Input functions following output functions. An input function cannot follow an output function without an intervening call to fflush, fseek, fsetpos, or rewind. The fflush function empties the buffer associated with a stream. The latter three functions use the Unix I/O lseek function to reset the current file position.
Restriction 2: Output functions following input functions. An output function cannot follow an input function without an intervening call to fseek, fsetpos, or rewind, unless the input function encounters an end-of-file.
But I cannot figure out why the restrictions imposed. So, my question is: what factors result to the two restrictions?
It also says that "It is illegal to use the lseek function on a socket.", but how is it possible fseek, fsetpos and rewind use lseek to reset the current file position if it is true?
There is a similar question here, but my question different from this one.
The stdio functions are for buffered file input and output. A socket is not a file, but a socket. It doesn't even have a file position, and the buffer requirements are quite distinct from ordinary files - sockets can have independent input and output buffers, stdio file I/O cannot!
The problem is that the file input and file output share the same file position, and the operating system might have (and indeed will have on Unix) a distinct file position from what the file position due to the buffering in C would be.
Hence, from C99 rationale
A change of input/output direction on an update file is only allowed following a successful
fsetpos, fseek, rewind, or fflush operation, since these are precisely the functions
which assure that the I/O buffer has been flushed.
Note that all this applies to only files opened with + - with files opened in any other standard modes, it is not possible to mix input and output.
Since it is required by the C standard that when switching from input to output on FILE * one of the functions fsetpos, rewind or fseek, which essentially invoke lseek must be successful (mind you, calling fflush causes the buffered output to be written, and certainly not discarding the buffered input) before an output function is attempted... yet a socket is not seekable and lseek would therefore always fail - it means that you cannot use a FILE * that has been opened for both reading and writing wrapping the socket for actually both reading from and writing to the socket.
It is possible to use fdopen to open a FILE * with stream sockets if you really need to: just open two files - one "rb" for input and another with "wb" for output.
When it says "An input function cannot follow an output function without an intervening call to fflush, fseek, fsetpos, or rewind", what it means is that if you don't, it might not work as you expect. But they're mostly talking about i/o to/from ordinary files.
If you have a FILE * stream connected to a socket, and you want to switch back and forth between writing and reading, I would expect it to work just fine if you called fflush when switching from writing to reading. I would not expect it to be necessary to call anything when switching from reading to writing.
(When working with files, the call to fseek or one of its relatives is necessary in order to update the file position properly, but streams don't have a file position to update.)
I think the reason is that, in the early days, the buffer is shared for read and write for most implementations.
The rationale is simple, most cases are uni-direction. And maintain 2 buffers for read and write respectively wastes space.
If you have only one buffer, when you change the IO direction, you need to deal with the buffer. That's why you need fflush, fseek, fsetpos, or rewind to either write the buffer to disk or empty the buffer in preparation for the next IO operation.
I checked one glibc implementation, which only uses one single buffer for read and write.
static void init_stream (register FILE *fp) {
...
fp->__buffer = (char *) malloc (fp->__bufsize);
if (fp->__bufp == NULL)
{
/* Set the buffer pointer to the beginning of the buffer. */
fp->__bufp = fp->__buffer;
fp->__put_limit = fp->__get_limit = fp->__buffer;
}
}
take fseek for example
/* Move the file position of STREAM to OFFSET
bytes from the beginning of the file if WHENCE
is SEEK_SET, the end of the file is it is SEEK_END,
or the current position if it is SEEK_CUR. */
int
fseek (stream, offset, whence)
register FILE *stream;
long int offset;
int whence;
{
...
if (stream->__mode.__write && __flshfp (stream, EOF) == EOF)
return EOF;
...
/* O is now an absolute position, the new target. */
stream->__target = o;
/* Set bufp and both end pointers to the beginning of the buffer.
The next i/o will force a call to the input/output room function. */
stream->__bufp
= stream->__get_limit = stream->__put_limit = stream->__buffer;
...
}
this implementation would flush the buffer to disk file if it's write mode.
And it will reset the pointer for both read and write. It's equivalent to reset or flush the buffer for read.
It matches the C99 (credit to the previous answer)
A change of input/output direction on an update file is only allowed following a successful fsetpos, fseek, rewind, or fflush operation, since these are precisely the functions which assure that the I/O buffer has been flushed.
For more details, check here.

Regarding printing characters in C

int main()
{
printf("Hello"); // doesn't display anything on the screen
printf("\n"); // hello is display on the screen
return 0;
}
All characters(candidate of printing) are buffered until a new line is received? Correct?
Q1 - Why does it wait before printing on terminal until a newline char?
Q2 - Where are the characters of first printf (i.e. "Hello") buffered?
Q3 - What is the flow of printing printf()->puts()->putchar() -> now where? driver? Does the driver has a control to wait until \n?
Q4 - What is the role stdout that is attached to a process?
Looking for a in-depth picture. Feel free to edit the question, if something doesn't makes sense.
printf is not writing directly to the screen, instead it writes to the output stream, which is by default buffered. The reason for this is, that there may not even be a screen attached and the output can go to a file as well. For performance reasons, it is better for a system if access to disc is buffered and then executed in one step with appropriately sized chunks, rather than writing every time.
You can even change the size of the buffer and set it to 0, which means that all output goes directly to the target, which may be usefull for logging purposes.
setbuf(stdout, NULL);
The buffer is flushed either when it is full, or if certain criterions are fullfilled, like printing a newline. So when you would execute the printf in a loop, you would notice that it will write out in chunks unless you have a newline inbetween.
I'll start with some definitions and then go on to answer your questions.
File: It is an ordered sequence of bytes. It can be a disk file, a stream of bytes generated by a program (such as a pipeline), a TCP/IP socket, a stream of bytes received from or sent to a peripheral device (such as the keyboard or the display) etc. The latter two are interactive files. Files are typically the principal means by which a program communicates with its environment.
Stream: It is a representation of flow of data from one place to another, e.g., from disk to memory, memory to disk, one program to another etc. A stream is a source of data where data can be put into (write) or taken data out of (read). Thus, it's an interface for writing data into or reading data from a file which can be any type as stated above. Before you can perform any operation on a file, the file must be opened. Opening a file associates it with a stream. Streams are represented by FILE data type defined in stdio.h header. A FILE object (it's a structure) holds all of the internal state information about the connection to the associated file, including such things as the file position indicator and buffering information. FILE objects are allocated and managed internally by the input/output library functions and you should not try to create your own objects of FILE type, the library does it for us. The programs should deal only with pointers to these objects (FILE *) rather than the objects themselves.
Buffer: Buffer is a block of memory which belongs to a stream and is used to hold stream data temporarily. When the first I/O operation occurs on a file, malloc is called and a buffer is obtained. Characters that are written to a stream are normally accumulated in the buffer (before being transmitted to the file in chunks), instead of appearing as soon as they are output by the application program. Similarly, streams retrieve input from the host environment in blocks rather than on a character-by-character basis. This is done to increase efficiency, as file and console I/O is slow in comparison to memory operations.
The C library provides three predefined text streams (FILE *) open and available for use at program start-up. These are stdin (the standard input stream, which is the normal source of input for the program), stdout (the standard output stream, which is used for normal output from the program), and stderr (the standard error stream, which is used for error messages and diagnostics issued by the program). Whether these streams are buffered or unbuffered is implementation-defined and not required by the standard.
GCC provides three types of buffering - unbuffered, block buffered, and line buffered. Unbuffered means that characters appear on the destination file as soon as written (for an output stream), or input is read from a file on a character-by-character basis instead of reading in blocks (for input streams). Block buffered means that characters are saved up in the buffer and written or read as a block. Line buffered means that characters are saved up only till a newline is written into or read from the buffer.
stdin and stdout are block buffered if and only if they can be determined not to refer to an interactive device else they are line buffered (this is true of any stream). stderr is always unbuffered by default.
The standard library provides functions to alter the default behaviour of streams. You can use fflush to force the data out of the output stream buffer (fflush is undefined for input streams). You can make the stream unbuffered using the setbuf function.
Now, let's come to your questions.
Unmarked question: Yes, becausestdout normally refers to a display terminal unless you have output redirection using > operator.
Q1: It waits because stdout is newline buffered when it refers to a terminal.
Q2: The characters are buffered, well, in the buffer allocated to the stdout stream.
Q3: Flow of the printing is: memory --> stdout buffer --> display terminal. There are kernel buffers as well controlled by the OS which the data pass through before appearing on the terminal.
Q4: stdout refers to the standard output stream which is usually a terminal.
Finally, here's a sample code to experiment things before I finish my answer.
#include <stdio.h>
#include <limits.h>
int main(void) {
// setbuf(stdout, NULL); // make stdout unbuffered
printf("Hello, World!"); // no newline
// printf("Hello, World!"); // with a newline
// only for demonstrating that stdout is line buffered
for(size_t i = 0; i < UINT_MAX; i++)
; // null statement
printf("\n"); // flush the buffer
return 0;
}
Yes, by default, standard output is line buffered when it's connected to a terminal. The buffer is managed by the operating system, normally you don't have to worry about it.
You can change this behavior using setbuf() or setvbuf(), for example, to change it to no buffer:
setbuf(stdout, NULL);
All the functions of printf, puts, putchar outputs to the standard output, so they use the same buffer.
If you wish, you can flush out the characters before the new line by calling
fflush(stdout);
This can be handy if you're slowly printing something like a progress bar where each character gets printed without a newline.
int main()
{
printf("Hello"); // Doesn't display anything on the screen
fflush(stdout); // Now, hello appears on the screen
printf("\n"); // The new line gets printed
return 0;
}

ftruncate on file opened with fopen

Platform is Ubuntu Linux on ARM.
I want to write a string to a file, but I want every time to truncate the file and then write the string, i.e. no append.
I have this code:
f=fopen("/home/user1/refresh.txt","w");
fputs( "{"some string",f);
fflush(f);
ftruncate(fileno(f),(off_t)0);
flcose(f);
If I run it and then check the file, it will be of zero length and when opened, there will be nothing in it.
If I remove the fflush call, it will NOT be 0 (will be 11) and when I open it there will be "some string" in it.
Is this the normal behavior?
I do not have a problem calling fflush, but I want to do this in a loop and calling fflush may increase the execution time considerably.
You should not really mix file handle and file descriptor calls like that.
What's almost certainly happening without the fflush is that the some string is waiting in file handle buffers for delivery to the file descriptor. You then truncate the file descriptor and fclose the file handle, flushing the string, hence it shows up in the file.
With the fflush, some string is sent to the file descriptor and then you truncate it. With no further flushing, the file stays truncated.
If you want to literally "truncate the file then write", then it's sufficient to:
f=fopen("/home/user1/refresh.txt","w");
fputs("some string",f);
fclose(f);
Opening the file in the mode w will truncate it (as opposed to mode a which is for appending to the end).
Also calling fclose will flush the output buffer so no data gets lost.
POSIX requires you to take specific actions (which ensure that no ugly side effects of buffering make your program go haywire) when switching between using a FILE stream and a file descriptor to access the same open file. This is described in XSH 2.5.1 Interaction of File Descriptors and Standard I/O Streams.
In your case, I believe it should suffice to just call fflush before ftruncate, like you're doing. Omitting this step, per the rules of 2.5.1, results in undefined behavior.

Defering FILE flush to when the file is closed

I want to defer flushing the contents of the FILE* to when fclose is called. In other words, I only want to write to disk when fclose is called and keep buffering the contents until then. Is it possible to do that with FILE* or I need to write my own code?
If you want to buffer (and under no circumstances write to the disk until the file is closed), then your best bet is to write to a buffer in memory (assuming that it will fit in memory, of course), and then write that buffer in one go and then call fclose().

Resources