Linux中I/O库函数(自学笔记)

一.I/O库概述

  1.I/O库

  库函数,其实就是将已写好的函数放到一个库中,供人们使用;

  I/O库函数,其实就是负责输入(input)及输出(output)的一类函数组成的库。

  方法是把一些常用到的函数编完放到一个文件里,供不同的人进行调用。调用的时候把它所在的文件名用#include<>加到里面就可以了。一般是放到lib文件里的。不受平台限制。

  2.流

  流是I/O库中一个比较重要的概念,对于标准I/O库,它们的操作都是围绕流进行的:

  对于标准的C函数库,文件操作都是围绕着流来进行的,流是一个抽象的概念,当程序需要读取数据的时候,开启一个通向数据源的流,数据源可以是文件,内存,网络连接等;当程序需要写入数据时,开启一个通向目的地的流,如下图:

  所以,当用标准I/O库打开或创建一个文件时,我们以使一个流与一个文件相关联。

  当打开一个流时(使用fopen函数),标准IO函数fopen返回一个指向FILE对象的指针。该对象通常是一个结构,它包含标准IO库为管理该流所需要的所有信息,包括用于实际IO的文件描述符、指向该流缓冲区的指针、缓冲区的长度、当前缓冲区中的字符数以及出错标志等。

  为了引用一个流,需要将FILE 指针作为参数传递给每个标准IO函数。我们称指向FILE对象的指针为文件指针。(FILE*)

 

 

   一般在代码中使用格式 FILE *fp。

  3.系统调用

  定义: 应用程序通过系统调用请求操作系统的服务

 系统中各种共享资源都由操作系统统一掌握,因此在用户程序中,凡是与资源有关的操作,都必须通过系统调用的方式向操作系统提出服务请求,由操作系统代为完成,这样可以保证系统的稳定性和安全性,防止用户进行非法操作。

  即:各种应用程序各种请求都是面向OS的,而相应的操作,由OS控制硬件完成。

  

 

 

 

二.I/O库算法(参考链接:https://blog.csdn.net/weixin_52042488/article/details/125743762)

  1.fopen —— fclose

      fopen函数

    FILE *fopen(const char *path,const char *mode);
    返回值:struct_IO_FILE, 在/usr/include/libio.h可以查看其定义
    这个结构体包含有:读写缓存的首地址,大小,位置指针等。
    那么对于特殊的“文件”,路径有如下:
    标准的输入流 stdin 0
    标准的输出流 stdout 1
    标准的出错流 stderr 2

      fclose函数

    调用成功返回0,失败返回EOF,并且设置errno
    在该文件被关闭之前,刷新缓存中的数据。如果标准I/O库已经为该流自动分配了一个缓存,则释放此缓存。

 

  2.fputs —— fgets 

      fputs函数

    char fgets(char s,int size,FILE *stream)
    第一个参数:缓存,即读到那里去
    第二个参数:读多少字节
    第三个参数:从什么地方读
    返回值:若成功则为s(缓存的地址),若已处文件尾端或者出错则为NULL

      fgets函数

    int fputs(const char* s,FILE *stream)

    第一个参数:缓存,即写什么内容
    第二个参数:写到哪里去
    返回值:若成功则为非负值,若出错则为EOF(一个宏定义,值为-1 )


  3.fread —— fwrite

    size_t fread(void* ptr,size_t size,size_t nmemb,FILE* fp);
    size_t fwrite(const void ptr,size_t size,size_t nmemb,FILE fp);

    功能:全缓存的读写函数

    第一个参数(char*)ptr:读的存放点/写的内容
    第二个参数:(size_t)size:每个读写单元内容的字节数
    第三个参数:(size_t)nmemb:读写内容有多少个单元
    第四个参数:(FILE*)fp:读写文件流

三.I/O库模式

  1.字符模式

实例:Linux系统中按字符复制文件

    命令:emacs mycs.c //打开空白文档

    代码作用:将原文件内容按字符复制到新文件中

    源代码:

复制代码
 1 #include <stdio.h>
 2 int main(int argc , char *argv[] )
 3 {
 4     FILE *fps , *fpd;
 5     int ch;
 6     if(argc <3)
 7     {
 8         printf("Usage : %s <src_file> <dst_file>\n",argv[0]);//如编译格式不对报错
 9         return -1;
10     }
11     if ((fps=fopen(argv[1],"r"))==NULL)
12     {
13         perror("fopen src file");//如不存在原文件as报错
14         return -1;
15     }
16     if ((fpd=fopen(argv[2],"r"))==NULL)
17     {
18         perror("fopen dst file");//如不存在原文件as报错
19         return -1;
20     }
21     while((ch = fgetc(fps))!=EOF)
22     {
23         fputc(ch,fpd);//从原文件中取字符,输入到新文件中
24     }
25     fclose(fps);
26     fclose(fpd);
27     return 0;
28 }//yaoyu-er
复制代码

    

    编译及验证环节:

 

 

  2.行模式

    char  *fgets(char  *buf,  int size,  FILE  *fp):从fp中读取最多为一行(以\n为结尾)的字符。

    int  fputs(char  *buf,  FILE  *fp):将buf中的一行写入fp中。

 

四.文件流缓冲(参考链接:https://blog.csdn.net/superSmart_Dong/article/details/120681145)

  每个文件流都包含有一个FILE 结构体,其中包含一个内部缓冲区。由于文件是存储在磁盘中。频繁的写磁盘耗时耗资源。通常把内容放在内存中,再把该内存中的数据一次性写入文件。缓冲方案有三种
  1)无缓冲 _IONBUF:每次读取的字符尽快地传输到文件或者从文件中传出,例如stderr

  2)  行缓冲 _IOLBUF:每次读取的字符写入到缓冲区中,读取到换行符时,再将缓冲区的内容传输/传出到文件,例如 stdout

  3)  全缓冲 _IOFBUF:把全部读取的字符都写入到缓冲区,再一次性传输/传出到文件。例如文件流 。

复制代码
 1 #include <stdio.h>
 2  
 3 int main(){
 4     //setvbuf(stdout,NULL,_IONBUF,0);
 5     int i=10;
 6     while(i--){
 7       printf("hi ");
 8       // fflush(stdout);
 9       sleep(1);
10     }
11 }
复制代码

  上面的案例直到程序执行完都不会看见输出的信息。因为stdout是行缓冲的,而循环体中都没遇见换行符。如果打开 setvbuf 注释,把stdout设置为无缓冲,那么输出的信息是每个字符每个字符地出现。如果打开 fflush 注释,把stdout的缓冲区清除,那么缓冲区内的信息再清除时都会被输出出来。

 

posted @   遥鱼  阅读(373)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示