标准IO和文件IO

简述

对文件进行操作,有文件IO和标准IO两种

标准IO: 采用库函数的方式对文件进行读写操作(对文件读写的函数接口出自于库)stdio.h

文件IO采用系统调用的方式对文件进行读写操作(对文件的读写操作功能有内核提供) ,并且不带缓存,

系统调用:内核提供的一个接口层,用用程序通过此接口可以实现内核为应用程序提供的各种功能

系统调用的流程:

         封装函数 -- 系统调用接口层(软中断)-- 系统调用的服务例程 -- 内核函数

 

一、标准I/O

标准IO是对文件IO的统合,类似于函数和命令的关系。而且每调用一次文件IO,处理器模式来回转换一次。

标准IO,将多次调用放到缓存区,到达一定程度在让处理器进行操作。

         文件IO没有缓存区,标准IO有缓存区

 系统调用发生三件事:

          1)处理器状态发生改变    由用户态切换为内核态(提高处理器的执行级别)

          2)系统调用的编号        每一个系统调用都会对应一个编号

          3)实现参数传递          先将参数放入到CPU寄存器,在执行内核函数之前,将参数取出,放入到内核进程的堆栈区

1、简介

标准IO当对文件进行操作时,先操作缓存区,然后等待缓存区满足一定条件时,在进行真正的读写操作,减少系统的调用的次数,提高对文件操作的效率

对文件操作,操作描述文件属性的结构体(FILE)指针

char* _IO_buf_base;   /* Start of reserve area. */  缓冲区的开始处

char* _IO_buf_end;    /* End of reserve area. */    缓冲区的结尾处  

 

标准IO(对文件读写的方式)

1)以字符的形式

2)以字符串的形式

3)以数据单元(二进制码)的形式

 

退出缓存区的三种方式

程序结束

缓存区填满

特定命令刷新,例如\n

标准IO中有三种类型的缓冲,下面会进行详细介绍

 

2、标准I/O的函数

2.1、 fopen

函数原型:FILE *fopen(const char *path, const char *mode);

功能:打开一个文件

参数:path  路径名(文件名)

      mode    r   以读的方式打开文件,如果文件不存在,报错(文件必须存在)

                    r+  以读写的方式打开文件,如果文件不存在,报错(文件必须存在)

                              

                               w   以写的方式打开文件,如果文件不存在,自动创建,如果文件存在,将文件中的数据清空

                               w+  以读写的方式打开文件,如果文件不存在,自动创建,如果文件存在,将文件中的数据清空

 

               a   以写的方式打开文件,如果文件不存在,自动创建,如果文件存在,将数据写入到文件的末尾

                               a+  以读写的方式打开文件,如果文件不存在,自动创建,如果文件存在,将数据写入到文件的末尾

 

返回值:成功  流指针(描述文件属性的结构体指针)

        失败  NULL

2.2、 perror和strerror

函数原型:void perror(const char *s);

功能:打印系统错误消息(消息保存在错误码errno)

函数原型:char *strerror(int errnum);

功能:返回对错误码的描述

参数:errno

2.3、 fputc

函数原型:int fputc(int c, FILE *stream);

功能:向文件中写入一个字符

参数:c  写入到文件中的字符

      stream  流指针(fopen函数的返回值)

           

返回值:成功  写入的字符

        失败  EOF

2.4、 fgetc

函数原型: int fgetc(FILE *stream);

功能:从文件中读取一个字符

参数:stream  流指针(fopen函数的返回值)

返回值:成功   返回读取的字符

        失败   EOF

2.5、 fputs

函数原型:int fputs(const char *s, FILE *stream);

功能:向文件中写入字符串

参数:s  写入文件中的字符串

      stream  流指针

返回值:成功  非负数

        失败  EOF

2.6、 fgets      

函数原型:     char *fgets(char *s, int size, FILE *stream); 

功能:从文件中读取字符串

参数:s  读取的字符串保存的位置

      size  设置读取的字节数

           stream  流指针

           

返回值:成功 返回读取的字符串

        失败 NULL

1)当文件中的数据字节数  >=  size ,  此时只能读取size-1个字符,最后一位自动补’\0‘,表示字符串到此读取结束

2)当文件中的数据字节数  <  size ,  此时将文件中的数据全部读出,在最后一位补’\0‘

 文件:abcd 

 fgets: N = 4

 读取结果:abc ’\0‘

 fgets:N = 7

 读取结果:abcd'\0'

1)当文件中的换行符’\n‘之前的数据字节数  >=  size, 读取size-1个字符,最后一位自动补’\0‘

2)当文件中的换行符’\n‘之前的数据字节数  <  size , 只能读取到'\n'之前所有的数据,fgets在'\n'补'\0',表示字符串到此读取结束

文件:abcd'\n'qwer'\n'

fgets:  N  =  128

读取结果:abcd'\n'\0'

2.7、 fclose

函数原型:int fclose(FILE *stream);

释放一个流指针。

函数退出后系统自动回收。

3、系统自定义的流指针

系统自定义的流指针(FILE *)--操作终端

 

标准I/O预定义3个流,他们可以自动地为进程所使用

 

stdin   标准输入      默认终端输入

stdout  标准输出      默认终端输出

stderr  标准出错输出  (报错)

函数原型:int fprintf(FILE *stream, const char *format, ...);

4、缓冲区

缓冲区的概念:

 标准IO中有三种类型的缓冲:

     1)全缓冲--当流与文件相关联的时候,此时操作的是全缓冲区

                     FILE *fp

                                     刷新条件:程序正常退出

                                               缓冲区写满

                                                          强制刷新  fflush();

                                              大小:4096

          2)行缓冲--当流与终端相关联的时候,此时操作的是行缓冲区

                     stdin  stdout

                                     刷新条件:程序正常退出

                                               缓冲区写满

                                                          强制刷新  fflush();

                                                          换行符"\n"

                                     大小:1024

          3)不缓冲--没有缓冲区

                     stderr

                大小:0

5、流的读写位置

5.1、 fseek

函数原型:int fseek(FILE *stream, long offset, int whence);

 功能:定位流的读写位置

 参数:stream  流指针

       offset  偏移量   相对于第三个参数再次发生的偏移

            whence  SEEK_SET  定位到文件的开始处

                    SEEK_CUR  定位到文件的当前位置

                               SEEK_END  定位到文件的末尾处

       fseek(fp, 0,SEEKSET);

返回值:成功  0

        失败  -1

5.2、 ftell

函数原型:long ftell(FILE *stream);

功能:获取当前读写位置(获取当前读写位置相对于文件开始处的偏移量)

参数:stream

返回值:成功  当前的读写位置

        失败  -1

6、以数据单元的形式对文件进行操作

数据单元的格式:字符、字符串、构造数据类型

6.1、 fwrite

函数原型:size_t fwrite(const void *ptr, size_t size, size_t nmemb,

                     FILE *stream);

功能:向文件中写入单元数据

参数:ptr  写入文件的数据单元

      size   写入文件的数据单元的大小

           nmemb  写入的数据单元的个数

           stream   流指针

返回值:  成功  > 0

          失败  < 0

                     

6.2、 fread

函数原型: size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

功能:从文件中读取数据单元

参数:ptr   从文件中读取的数据

           size  读取的数据单元的大小

           nmemb  读取的数据单元的个数

           stream  流指针

返回值:成功  > 0

        失败  < 0

注意:fwrite与fread函数都是对二进制码进行操作,所以如果写入的是数字,将会是一种类似于乱码的形式

二、文件IO

文件IO的本质:系统调用  

文件I/O的特殊性:可以操作硬件

1、文件描述符

标准IO;操作核心--流指针

文件IO: 操作核心--文件描述符

文件描述符的特点:

1、 文件描述符是一个非负整数。当打开一个现存文件或创建一个新文件时,内核向进程返回一个文件描述符。

2、文件描述符本质上讲,就是一个值,通过文件描述符可以对文件进行操作,文件的标识通过inode号区分,不同的文件inode

3、当打开一个文件的时候,系统会自动生成三个文件描述符,分别是  0   1   2 ,分别对应的文件是标准输入文件,标准输出文件,标准出错文件

4、同一个进程,文件描述符的值最大不能超过1024

5、同一个进程,文件描述符不会出现重复

2、打开关闭文件函数

 函数原型:int open(const char *pathname, int flags);

                   int open(const char *pathname, int flags, mode_t mode);

 功能:打开一个文件或设备文件(硬件设备)

 参数:pathname  文件名

       flags     标志位     O_RDONLY  以只读的方式打开一个文件

                                    O_WRONLY  以只写的方式打开一个文件

                                    O_RDWR    以读写的方式打开一个文件

                                     O_APPEND  以追加的方式打开一个文件

                                     O_CREAT   文件不存在,自动创建

                                     O_EXCL    文件存在,报错

                                     O_TRUNC   如果文件存在,将文件中的数据清空

        r   对应 O_RDONLY   以只读的方式打开一个文件,如果文件不存在,报错

         r+  对应O_RDWR     以读写的方式打开一个文件,如果文件不存在,报错

         w  对应O_WRONLY|O_CREAT|O_TRUNC; 以只写的方式打开一个文件,如果文件不存在,创建;如果文件存在,清空数据

         w+ 对应 O_RDWR|O_CREAT|O_TRUNC;以读写的方式打开一个文件,如果文件不存在,创建;如果文件存在,清空数据

         a  对应O_WRONLY|O_CREAT|O_APPEND;以只写的方式打开一个文件,如果文件不存在,创建;如果文件存在,写入到文件的末尾

         a+ 对应O_RDWR|O_CREAT|O_APPEND;以读写的方式打开一个文件,如果文件不存在,创建;如果文件存在,写入到文件的末尾

O_WRONLY | O_RDONLY   不等于 O_RDWR  :因为他们都是宏定义,实际上是八位二进制数

                                                          

      mode   指定该文件所属的用户对其执行权限        0666

                             如果第二个参数指定O_CREAT,必须有第三个参数 ;文件权限为(mode & ~umask). ; mode可以有两种方式书写,一种为八进制数字,一种为字符形式,详细可以使用man查看

 

umask的作用是自动屏蔽一些用户权限

返回值:成功         文件描述符

        失败   -1

 

函数原型:int close(int fd);

关闭一个文件描述符

 

3、文件I/O的读写函数                             

3.1、写函数 write

函数原型:     ssize_t write(int fd, const void *buf, size_t count);        

功能:向文件中写入count个字节数据(不论数据格式,只论写入的字节数)

参数:fd  文件描述符

      buf  写入文件的数据

           count  需要写入的字节数

返回值:成功  实际写入的字节数

        失败  -1

3.2、读函数 read

函数原型:ssize_t read(int fd, void *buf, size_t count);

功能:期望从文件中读取count个字节的数据

参数:fd  文件描述符

      buf  读取的数据保存位置

           count  期望读取的字节数

返回值:成功 实际读取的字节数

        0    当前的读写位置在文件末尾处

        失败 -1

文件IO 的读写方式的参数分配,第一个参数为文件位

                             第二个为数据位

                             第三个为数据字节数

4、文件描述符的读写位置

函数原型:off_t lseek(int fd, off_t offset, int whence);                                                          

功能:定位文件的读写位置

参数:fd  文件描述符

          offset   相对于第三个参数偏移量

          whence  SEEK_SET  定位到文件的开始处

                        SEEK_CUR  定位到文件的当前读写位置

                         SEEK_END  定位到文件的末尾

返回值:成功   返回定位的位置相对于文件开始处的偏移量

        失败   -1

不同于标准io的fseek函数,返回值为偏移量,而不是-1 or 0;

5、目录读取

1、获得目录函数接口:(目录的open函数)

函数原型: DIR *opendir(const char *name);

功能:打开一个目录,获得目录流指针

参数:name  目录名

返回值:成功  目录流指针

         失败  NULL

2、读取目录(一个文件一个文件的读)           

函数原型: struct dirent *readdir(DIR *dirp);

功能:读取目录,返回一个描述文件信息的结构体

 参数:dirp   目录流指针

 返回值:成功  struct  dirent  *    

                               struct dirent {

                                               char   d_name[256]  文件名

                               }

         失败  NULL

6、获取文件的属性信息

函数原型:int stat(const char *path, struct stat *buf);

功能:获取文件的属性信息,保存在第二参数中

参数:path   文件名

      buf    保存文件属性的结构体

           struct stat {

               dev_t     st_dev;     /* ID of device containing file */   设备号

               ino_t     st_ino;     /* inode number */               索引号

               mode_t    st_mode;    /* protection */

               nlink_t   st_nlink;   /* number of hard links */     硬链接数

               uid_t     st_uid;     /* user ID of owner */         所属用户的ID  1000

               gid_t     st_gid;     /* group ID of owner */        组ID

               dev_t     st_rdev;    /* device ID (if special file) */  

               off_t     st_size;    /* total size, in bytes */        文件的大小

               time_t    st_atime;   /* time of last access */       上一次进入文件的时间  

               time_t    st_mtime;   /* time of last modification */     上一次修改文件的时间

               time_t    st_ctime;   /* time of last status change */    上一次文件状态改变的时间

           };

返回值:成功  0

        失败   -1

标准I/O和文件I/O的函数对应

                                             

 

 

扩展

         相关内容请看UNIX系统编程手册上册,第五章

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值