Overview:
C has two sets of binary stream files for reading and writing in UNIX: fread() and fwrite(). fwrite() is a function that writes to a FILE*, which is a (possibly) buffered stdio stream. The ISO C standard specifies it. Furthermore, fwrite() is thread-safe to a degree on POSIX platforms. The POSIX standard defines write as a lower-level API based on file descriptors. It is unaware of the concept of buffering. If you wish to use it on a FILE*, use file to get its file descriptor, but lock and flush the stream manually before performing to write. Unless you’re sure what you’re doing, use fwrite().
Note –
One thing to keep in mind is that accessing a FILE* structure from multiple threads (which includes, but is not limited to, executing fread/fwrite) is often riskier than doing so with low-level file descriptors.
Takeaway:
- The write function is a call to the operating system made by your application, it is slower than fwrite().
- It also lacks buffering, which makes it considerably sluggish because, as the buffering theory implies, “it is faster to process several tiny files than a large one.”
- It’s also worth noting that write isn’t part of the C standard, thus you won’t find it on non-POSIX systems, and the appropriate use may change (rarely).
- It’s also worth noting that write and read are sometimes used to implement fwrite() and fread() (a simple implementation can be found in the chapter about Unix of K&R).
- One more distinction between write and fwrite is that write is atomic whereas fwrite is not.
Example –
Consider the following Code Sample as follows.
Sample code-1:
#include <stdlib.h> #include <stdio.h> #include <string.h> #include <unistd.h> int main() {
if (fork() == 0) {
// open file for append
//Checking if fork is really 0
FILE * h = fopen ( "file.txt" , "a" );
// line is a pointer which is of char type
char * line =
"gggggggggggggggggggggggggggggggggggggggggggggggg\n" ;
// logic if condition not match
// then line will not be append to file.
//Looping till the condition of printing is not fulfilled!
for ( int i = 0; i < 1000; i++) {
if (write(fileno(h), line, strlen (line)) != strlen (line)) {
perror ( "Could not append line to file" );
//There was some error, this is exception handling
exit (1);
}
}
// close file on the basis of condition
if ( fclose (h) != 0) {
perror ( "Could not close file" );
exit (1);
}
} else {
//Opening and Writing on a Text File
FILE * h = fopen ( "file.txt" , "a" );
char * line =
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n" ;
for ( int i = 0; i < 1000; i++) {
if (write(fileno(h), line, strlen (line)) != strlen (line)) {
perror ( "Could not append line to file" );
exit (1);
}
}
if ( fclose (h) != 0) {
perror ( "Could not close file" );
//Exception Handling if file could not be closed
exit (1);
}
}
return 0;
} |
Output :
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb gggggggggggggggggggggggggggggggggggggggggggggggg bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb gggggggggggggggggggggggggggggggggggggggggggggggg bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb gggggggggggggggggggggggggggggggggggggggggggggggg bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb gggggggggggggggggggggggggggggggggggggggggggggggg bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
Sample code-2:
As you may see, there are no interleaving lines in the output Now, consider this sample code as follows.
#include <stdlib.h> #include <stdio.h> #include <string.h> #include <unistd.h> int main() {
//Checking the fork condition again
if (fork() == 0) {
FILE * h = fopen ( "file.txt" , "a" );
//Creating a char line, similar to the code above
char * line =
"gggggggggggggggggggggggggggggggggggggggggggggggg\n" ;
for ( int i = 0; i < 1000; i++) {
if ( fwrite (line, 1, strlen (line), h) != strlen (line)) {
perror ( "Could not append line to file" );
//Exception Handling
exit (1);
}
}
if ( fclose (h) != 0) {
perror ( "Could not close file" );
//File could not be closed
exit (1);
}
} else {
//Opening the file again
FILE * h = fopen ( "file.txt" , "a" );
char * line =
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\n" ;
for ( int i = 0; i < 1000; i++) {
if ( fwrite (line, 1, strlen (line), h) != strlen (line)) {
perror ( "Could not append line to file" );
//Exception Handling
exit (1);
}
}
if ( fclose (h) != 0) {
perror ( "Could not close file" );
exit (1);
}
}
return 0;
} |
Output :
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbggggggggggggggggggggggggggggggggggggg ggggggggggg gggggggggggggggggggggggggggggggggggggggggggggggg gggggggggggggggggggggggggggggggggggggggggggggggg gggggggggggggggggggggggggggggggggggggggggggggggg gggggggggggggggggggggggggggggggggggggggggggggggg gggggggggggggggggggggggggggggggggggggggggggggggg
Difference between fwrite() and write():
Feature | fwrite() | write() |
Purpose | Write to a FILE stream | Write to a file descriptor |
Buffering | Buffered I/O | Unbuffered I/O |
Standard | Part of C standard | Not part of C standard, POSIX-specific |
Thread-safety | Thread-safe | Thread-safe |
Implementation detail | Uses write() internally | Lower-level than fwrite() |
Atomicity | Not atomic | Atomic |
Performance | Slower | Faster |
Error handling | Returns error status | Returns -1 on error |
Conclusion :
Here comes the interviewing lines into play, hence stipulating the latter to be non-atomic and the former to be atomic. Hope this clears away the ever slightest difference between fwrite() & write(). The Difference is small, only key factors change!