Linux下标准IO库(上篇) ---学习笔记四

113 阅读6分钟
  1. 标准IO库和FILE指针
  • 1.1 标准IO库
  • 1.2 FILE指针
  1. 标准IO库函数
  • fopen()
  • fread()
  • fwrite()
  • fclose()
  • fseek()
  • ftell()
  • 示例
  1. 文件末尾和错误标志的检测与清除
  • 文件末尾的检查feof()函数
  • 错误标志的检查ferror()函数
  • 文件末尾和错误标志的清除clearerr()函数
  • 示例

1 标准IO库和FILE指针

1.1 标准IO库

标准IO库即是标准的C库中用于IO操作的函数,例如读写操作的函数,这些函数相关定义都在<stdio.h>头文件中,所以使用这些函数需要包含头文件<stdio.h>。

标准C库IO操作函数(fopne()、fread()、fwrite()、fclose()、flseek())都是系统调用之上封装后的函数,内部也是调用opne()、read()、write()、close()、lseek()等系统调用函数。

标准IO与文件IO区别在于,同为C语言程序,但标准IO是C库函数,文件IO是Linux系统调用,标准IO是文件IO封装而来的,标准IO的可移植性更好,相对于文件IO,不同操作系统的定义,参数,返回值可能不一致,但是对于标准IO来说在不同操作系统的接口定义几乎是一致的。标准IO的性能效率要更好,因为文件IO在用户空间是不带缓存,而标准IO是在用户空间维护字节的stdio缓存区,所以在性能和效率上要更好。

1.2 FILE指针

文件IO的操作函数都是围绕着文件描述符进行运行,例如open函数打开或创建成功后会返回一个文件描述符fd,但对于标准IO库函数来说,使用fopen函数打开或创建成功后会返回一个指向 FILE 类型对象的指针(FILE * );作用相当于文件描述符fd。

FILE是一个结构体的数据类型,其包含了实际的IO文件描述符,指向文件缓存区的指针,缓存区长度、当前缓冲区的字节数、错误标志等。

标准输入0、标准输出1、标准错误2这三个文件描述符在进程每次确定都会打开,只用于文件IO中,但C库中的标准IO是由文件IO封装而来,故也无法使用,

标准输入:指的是计算机系统的标准的输入设备,通常指的是计算机所连接的键盘,进程从标准输入(stdin)文件中得到输入数据; 标准输出:指的是计算机系统中用于输出标准信息的设备,通常指的是计算机所连接的显示器,正常输出数据输出到标准输出(stdout)文件; 标准错误:指的是计算机系统中用于显示错误信息的设备,通常也指的是显示器设备,错误信息输出到标准错误(stderr)文件。

2 标准IO库函数

2.1 fopen()

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

输入参数

path:文件打开或者创建的路径,绝对路径或是相对路径。

mode: 指定了对该文件的读写权限,是一个字符串。

返回值:成功返回一个指向 FILE 类型对象的指针(FILE * ),失败则返回NULL。

参数mode的字符串类型

r:只读方式打开文件,相当于open函数的O_RDONLY标志;

r+:可读可写的方式打开文件,相当于open函数的O_RDWR标志;

w:只写方式打开文件,参数path的文件路径存在则将文件长度截断为0;不存在则创建该文件,相当于open函数的 O_WRONLY | O_CREAT | O_TRUNC标志;

w+:可读可写的方式打开文件,参数path的文件路径存在则将文件长度截断为0;不存在则创建该文件,相当于open函数的 O_RDWR | O_CREAT | O_TRUNC标志;

a:只写方式打开文件,打开文件在末尾开始写入,文件不存在则创建,相当于open函数的 O_WRONLY | O_CREAT | O_APPEND标志;

a+:可读可写的方式打开文件,打开文件在末尾开始写入,文件不存在则创建,相当于open函数的 O_RDWR | O_CREAT | O_APPEND标志;

2.2 fread()

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

输入参数

ptr:读取到的数据放入参数ptr指向的缓冲区;

size:读取的每个数据项的字节大小;

nmemb:读取的数据项个数;

stream:FILE指针。

返回值:成功时返回读取到的数据项的数目(总共读取的数据大小为 nmemb * size 个字节),如果发生错误或到达文件末尾,则 fread()返回的值将小于参数nmemb,可以使用ferror()或feof()判断是发生错误还是到达文件末尾。

2.3 fwrite()

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

输入参数

ptr:ptr指向的被写入的数据缓冲区;

size:写入的每个数据项的字节大小;

nmemb:写入的数据项个数;

stream:FILE指针。

返回值:成功时返回写入的数据项的数目(总共读取的数据大小为 nmemb * size 个字节),如果发生错误,则 fwrite()返回的值将小于参数 nmemb(或者等于 0)。

2.4 fclose()

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

输入参数 stream:FILE指针。

返回值:成功返回0,失败返回-1。

2.5 fseek()

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

输入参数

stream:FILE指针。

offset:与 lseek()函数的 offset 参数意义相同。

whence:与 lseek()函数的 whence 参数意义相同。

返回值:成功返回0,错误返回-1。

2.6 ftell()

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

输入参数

stream:FILE指针。

返回值:成功返回当前读写位置偏移量,错误返回-1。

2.7 示例

将write_buf缓存区数据写入文件a.c,后将文件a.c数据的读取到read_buf #include <stdio.h> #include <stdlib.h>

int main()
{
    FILE *fp = NULL;
    char write_buf[] = "aaabbbccc"
    char read_buf[100] = {0};
    int ret;
    
    fp = fopen("./home/a.c","w+");
    if(fp == NULL)
    {
        perror("fopen ERROR");
        exit(-1);
    }
    
    if(sizeof(write_buf) > fwirte(write,1,sizeof(write_buf),fp))
    {
        perror(fwrite ERROR);
        close(fp);
        exit(-1);
    }
    
    
    if(-1 == fseek(fd,0, SEEK_SET))
    {
        perror(fseek ERROR);
        close(fp);
        exit(-1);
    }
    
    if(sizeof(write_buf) > fread(read,1,sizeof(write_buf),fp))
    {
        perror(fread ERROR);
        close(fp);
        exit(-1);
    }
    
    if(-1 == (ret = ftell(fp)))
    {
        perror(ftell ERROR);
        close(fp);
        exit(-1);
    }
    
    printf("%d,%s",ret,read);

    close(fp);
    exit(0);
}

3 文件末尾和错误标志的检测与清除

3.1 文件末尾的检查feof()函数

feof()函数用于检测参数stream所指文件的end-of-file 标志是否有被设置。

函数原型:int feof(FILE *stream)

输入参数

stream:FILE指针

返回值:end-of-file 标志被设置返回一个非零值,end-of-file 标志没被设置返回0。

3.2 错误标志的检查ferror()函数

ferror()函数用于检测参数stream所指文件的错误标志是否有被设置。

函数原型:ferror(FILE *stream)

输入参数

stream:FILE指针

返回值:错误标志被设置返回一个非零值,错误标志没被设置返回0。

3.3 文件末尾和错误标志的清除clearerr()函数

ferror()函数)用于清除end-of-file标志和错误标志,除了使用 clearerr()显式清除之外,当调用 fseek()成功时,也会清除文件的end-of-file 标志.

file 标志。

函数原型:clearerr(FILE *stream);

输入参数

stream:FILE指针

返回值:无返回值

3.4 示例

#include <stdio.h>
#include <stdlib.h>

int main()
{
    FILE *fp = NULL;
    char read_buf[100] = {0};
    int ret;
    
    fp = fopen("./home/a.c","r");
    if(fp == NULL)
    {
        perror("fopen ERROR");
        exit(-1);
    }
    
    
    if(-1 == fseek(fd,0, SEEK_END))
    {
        perror(fseek ERROR);
        close(fp);
        exit(-1);
    }
    
    
    if(9 > fread(read,1,9,fp))
    {
        perror(fread ERROR);
        close(fp);
        exit(-1);
        if (feof(fp))
        {
            printf("end-of-file标志已被设置,已到文件末尾\n\r");
        }
        clearerr(fp);
    }
    
    close(fp);
    exit(0);
    
}