【Linux】基础IO 知识点

阳光穿透心脏的1/2处 2021-12-02 01:12 379阅读 0赞

C文件

1. 写入文件

  1. ...
  2. 6 FILE *fp=fopen("myfile","w");
  3. ...
  4. 11 const char*msg="hello world!\n";
  5. 12 int count=5;
  6. 13 while(count--)
  7. 14 {
  8. 15 fwrite(msg,strlen(msg),1,fp);
  9. 16 }
  10. 17 fclose(fp);

在这里插入图片描述
其中 fwrite(msg,strlen(msg),1,fp); 用来写入文件,msg 是写入字符串的首地址,strlen(msg) 是写入的标准长度,1是写入的基本单位,fp是写入文件的文件名。
2. 读取文件

  1. 1 #include <stdio.h>
  2. 2 #include <string.h>
  3. 3 #include <error.h>
  4. 4 int main()
  5. 5 {
  6. 6 FILE *fp=fopen("myfile","r");
  7. 7 if(!fp)
  8. 8 {
  9. 9 perror("fopen");
  10. 10 }
  11. 11 char buf[1024];
  12. 12 const char *msg="hello world!\n";
  13. 13 while(1)
  14. 14 {
  15. 15 ssize_t s=fread(buf,1,strlen(msg),fp);
  16. 16 if(s>0)
  17. 17 {
  18. 18 buf[s]=0;
  19. 19 printf("%s",buf);
  20. 20 }
  21. 21 if(feof(fp))
  22. 22 {
  23. 23 break;
  24. 24 }
  25. 25 }
  26. 26 fclose(fp);
  27. 27 return 0;
  28. 28 }

在这里插入图片描述
其中fread(buf,1,strlen(msg),fp);函数用来读取fp 中的文件
但是这个函数的返回值和参数要特别注意,小心有坑。
在这里插入图片描述
3. 输出信息到显示器上
将C文件信息输出到显示器上有三种方法:
1)fwrite 将信息直接写在标准输出(显示器)上
2)printf 输出
3)fprintf 给文件指定输出位置

以下代码可以验证:

  1. 1 #include <stdio.h>
  2. 2 #include <string.h>
  3. 3
  4. 4 int main()
  5. 5 {
  6. 6 const char* msg="hello fwrite!\n";
  7. 7 fwrite(msg,strlen(msg),1,stdout);
  8. 8
  9. 9 printf("hello printf!\n");
  10. 10 fprintf(stdout,"hello fprintf!\n");
  11. 11 return 0;
  12. 12 }

在这里插入图片描述

4. 文件打开方式

r : 只读方式,光标出现在文件开始的位置。
r+/w+ : 读写方式 ,光标在文件开始的位置。
w : 只写方式,光标在文件开始的位置。
a : 追加方式,光标在文件的末尾。
a+ : 读并追加,光标在文件末尾的位置。

C文件主要调用<stdio.h>头文件中包含的库函数,这些函数本质是对系统调用的封装。操作C文件的函数还有 fseek,ftell,fewind等。大家在学习C语言时应该接触过,这里就不细讲了。

系统文件 I/O

对于文件,我们也常使用系统接口进行访问

open
在这里插入图片描述
其中pathname 是(打开或创建的)文件名,flags 是文件的打开方式,mode 是文件的打开权限。

flags(文件打开方式 )的参数
O_RDONLY :只读
O_WRONLY:只写
O_RDWR:读写
上述三个常量必须指定一个且只能指定一个
O_CREAT:若文件不存在就创建,需要mode指明文件的权限
O_APPEND:追加写
返回值
成功:新打开文件的文件描述符
失败:-1

read

  1. read(0,buf,sizeof(buf));

其中第一个参数是从哪里开始读,第二个参数是读的内容,第三个参数是读的大小。

函数返回值: 成功: >0 失败:<0 读到结尾:=0

write

  1. write(1,buf,strlen(bf));

FILE 及 缓冲区

FILE 结构体是由C库定义的,且必定是在系统调用基础上封装了fd。
首先看下面代码的现象:

  1. #include <stdio.h>
  2. #include <string.h>
  3. int main()
  4. {
  5. const char* s1="hello printf\n";
  6. const char* s2="hello fwrite\n";
  7. const char* s3="hello write \n";
  8. printf("%s",s1);
  9. fwrite(s2,strlen(s2),1,stdout);
  10. write(1,s3,strlen(s3));
  11. fork();
  12. return 0;
  13. }

在这里插入图片描述
通过结果,我们发现即使同样被fork()了一个子进程,但是fwrite在显示器上打印一次却在file中打印两次,而write 无论在哪里都只被打印一次。这是为什么呢?

这里其实是因为缓冲区刷新条件的缘故。
一般库函数在写入文件时是全缓冲而写入显示器是行缓冲;系统函数无论在哪都是行缓冲。
所以在显示器上,二者都只能输出一次。
但在文件中:这时因为库函数调用fwrite()时默认全缓冲,因此函数在调用fork()时子进程仍可以拷贝父进程缓冲区中的内容,最后进程退出时统一刷新文件缓冲区,所以文件中出现了两份相同的内容。而系统调用write()时仍默认行缓冲,函数在调用fork()时,父进程缓冲区内内容已被刷新出去,子进程发现没有内容可以拷贝,就只有一份内容。

此时若我们强制刷新库函数的缓冲区会发生什么现象呢?
下面是我用fflush(stdout);刷新printf 缓冲区后的现象
在这里插入图片描述

经此验证,我们发现库函数会自带缓冲区,但是系统调用没有带缓冲区。我们又知道库函数调用在系统调用的上层,所以说明缓冲区是通过C库二次加上去的。

这里需要注意:
行缓冲:遇到“\n”就会刷新缓冲区
全缓冲:写满缓冲区时才能被刷新
无缓冲:例如标准输入

发表评论

表情:
评论列表 (有 0 条评论,379人围观)

还没有评论,来说两句吧...

相关阅读

    相关 iOS 知识梳理

    OC的理解与特性 OC作为一门面向对象的语言,自然具有面向对象的语言特性:封装、继承、多态。它既具有静态语言的特性(如C++),又有动态语言的效率(动态绑定、动态加载等