📜  fwrite() 与 write()

📅  最后修改于: 2022-05-13 01:57:14.390000             🧑  作者: Mango

fwrite() 与 write()

概述:
C 有两组用于在 UNIX 中读写的二进制流文件:fread() 和 fwrite()。 fwrite() 是一个写入 FILE* 的函数,它是一个(可能)缓冲的 stdio 流。 ISO C 标准对其进行了规定。此外, fwrite() 在 POSIX 平台上在一定程度上是线程安全的。 POSIX 标准将 write 定义为基于文件描述符的较低级别的 API。它不知道缓冲的概念。如果您希望在 FILE* 上使用它,请使用 file 获取其文件描述符,但在执行写入之前手动锁定和刷新流。除非您确定自己在做什么,否则请使用 fwrite()。

笔记 -
要记住的一件事是,从多个线程(包括但不限于执行 fread/fwrite)访问 FILE* 结构通常比使用低级文件描述符这样做风险更大。

带走:

  1. write函数是应用程序对操作系统的调用,它比 fwrite() 慢。
  2. 它还缺乏缓冲,这使得它相当缓慢,因为正如缓冲理论所暗示的那样,“处理几个小文件比处理大文件要快。”
  3. 还值得注意的是 write 不是 C 标准的一部分,因此您不会在非 POSIX 系统上找到它,并且适当的使用可能会改变(很少)。
  4. 还值得注意的是,有时使用 write 和 read 来实现 fwrite() 和 fread() (一个简单的实现可以在 K&R 的有关 Unix 的章节中找到)。
  5. write 和 fwrite 之间的另一个区别是 write 是原子的,而 fwrite 不是。

例子 -
考虑以下代码示例。

示例代码-1:



C
#include 
#include 
#include 
#include 
 
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;
}


C
#include 
#include 
#include 
#include 
 
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;
}


输出 :

bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
gggggggggggggggggggggggggggggggggggggggggggggggg
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
gggggggggggggggggggggggggggggggggggggggggggggggg
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
gggggggggggggggggggggggggggggggggggggggggggggggg
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
gggggggggggggggggggggggggggggggggggggggggggggggg
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb

示例代码-2:
如您所见,输出中没有交错行 现在,请考虑如下示例代码。

C

#include 
#include 
#include 
#include 
 
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;
}

输出 :

bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbggggggggggggggggggggggggggggggggggggg
ggggggggggg
gggggggggggggggggggggggggggggggggggggggggggggggg
gggggggggggggggggggggggggggggggggggggggggggggggg
gggggggggggggggggggggggggggggggggggggggggggggggg
gggggggggggggggggggggggggggggggggggggggggggggggg
gggggggggggggggggggggggggggggggggggggggggggggggg

结论 :
这里出现了面试线,因此规定后者是非原子的,而前者是原子的。希望这消除了 fwrite() 和 write() 之间最细微的区别。差异很小,只有关键因素改变!