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!