【Linux学习】标准IO库

以下是关于Linux标准IO库的介绍和基本使用,希望对您有所帮助。

如果我的文章让你感兴趣,可以点赞收藏关注一波。

作者:小海编程心语录-CSDN博客

1.标准IO库简介

  • 标准 I/O 库是标准 C 库中用于文件 I/O 操作(譬如读文件、写文件等)相关的一系列库函数的集合,通常标准 I/O 库函数相关的函数定义都在头文件中
  • 标准 I/O 库函数是构建于文件 I/O(open()、 read()、 write()、 lseek()、 close()等)这些系统调用之上的
  • 标准 I/O 和文件 I/O 的区别如下
    • 虽然标准 I/O 和文件 I/O 都是 C 语言函数,但是标准 I/O 是标准 C 库函数,而文件 I/O 则是 Linux 系统调用
    • 标准 I/O 是由文件 I/O 封装而来,标准 I/O 内部实际上是调用文件 I/O 来完成实际操作的
    • 可移植性:标准 I/O 相比于文件 I/O 具有更好的可移植性,标准 I/O 库在不同的操作 系统之间其接口定义几乎是一样的
    • 性能、效率: 标准 I/O 库在用户空间维护了自己的 stdio 缓冲区, 所以标准 I/O 是带有缓存的,而 文件 I/O 在用户空间是不带有缓存的,所以在性能、效率上,标准 I/O 要优于文件 I/O

 1.1 FILE指针

对于标准 I/O 库函数来说, 当使用标准 I/O 库函数打开或创建一个 文件时,会返回一个指向 FILE 类型对象的指针(FILE *) ,使用该 FILE 指针与被打开或创建的文件相关联,然后该 FILE 指针就用于后续的标准 I/O 操作

  • FILE 是一个结构体数据类型(结构体_IO_FILE的别名宏),它包含了标准 I/O 库函数为管理文件所需要的所有信息,包括用于实际 I/O 的文件描述符、指向文件缓冲区的指针、缓冲区的长度、当前缓冲区中的字节数以及出错标志等。 FILE 数据结构定义在标准 I/O 库函数头文件 stdio.h 中
    • 系统IO:打开文件得到的是一个整数,称为文件描述符
    • 标准IO:打开文件得到的是一个指针,称为文件指针

1.2 标准输出、出错、输入

  • 0、 1、 2 这三个是文件描述符,只能用于文件 I/O,在标准 I/O 中,无 法使用文件描述符来对文件进行 I/O 操作的,它们需要围绕 FILE 类型指针来进行。
  • 在标准 I/O 中,可以使用 stdin、 stdout、 stderr 来表示标准输入、标准输出和标准错误

2.文件操作

2.1 fopen()

//函数原型
#include <stdio.h>
FILE *fopen(const char *path, const char *mode);

 函数参数和返回值含义如下: 

path: 参数 path 指向文件路径,可以是绝对路径、也可以是相对路径。

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

返回值: 调用成功返回一个指向 FILE 类型对象的指针(FILE *), 如果失败则返回 NULL,并设置 errno 以指示错误原因。

 参数 mode 字符串类型,可取值为如下值之一: 

mode

说明

对应于 open()函数的 flags 参数取值

r

以只读方式打开文件

O_RDONLY

r+

以可读、可写方式打开文件

O_RDWR

w

以只写方式打开文件,如果参数 path 指定的文件存在,将文件长度截断为 0;如果指定文件不存在则创建该文件

O_WRONLY | O_CREAT | O_TRUNC

w+

以可读、可写方式打开文件,如果参数 path 指定的文件存在,将文件长度截断为 0;如果指定文件不存在则创建该文件

O_RDWR | O_CREAT | O_TRUNC

a

以只写方式打开文件,打开以进行追加内容(在文件末尾写入),如果文件不存在则创建该文件

O_WRONLY | O_CREAT | O_APPEND

a+

以可读、可写方式打开文件,以追加方式写入(在文件末尾写入),如果文件不存在则创建该文件

O_RDWR | O_CREAT | O_APPEND

2.2 fclose()

  • 关闭一个由 fopen()打开的文件
//函数原型
#include <stdio.h>
int fclose(FILE *stream);

参数 stream 为 FILE 类型指针,调用成功返回 0;失败将返回 EOF(也就是-1),并且会设置 errno 来 指示错误原因 

2.3 fread()

  • fread()用于读取文件数据
//函数原型
#include <stdio.h>
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

函数参数和返回值含义如下:

ptr:fread()将读取到的数据存放在参数 ptr 指向的缓冲区中;

size:fread()从文件读取 nmemb 个数据项,每一个数据项的大小为 size 个字节,所以总共读取的数据大 小为 nmemb * size 个字节。

nmemb: 参数 nmemb 指定了读取数据项的个数。

stream: FILE 指针。

返回值: 调用成功时返回读取到的数据项的数目;如果发生错误或到达文件末尾,则 fread()返回的值将小于参数 nmemb,那么到底发生了错误 还是到达了文件末尾, fread()不能区分文件结尾和错误,此时可以使用 ferror()或 feof() 函数来判断

2.4 fwrite()

  • fwrite()用于将数据写入到文件中
//函数原型
#include <stdio.h>
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

函数参数和返回值含义如下:

ptr: 将参数 ptr 指向的缓冲区中的数据写入到文件中。

size: 参数 size 指定了每个数据项的字节大小。

nmemb: 参数 nmemb 指定了写入的数据项个数。

stream: FILE 指针。

返回值: 调用成功时返回写入的数据项的数目;如果发生错误,则 fwrite()返回的值将小于参数 nmemb(或者等于 0)

库函数 fread()、 fwrite()中指定读取或写入数据大小的方式与系统调用 read()、 write()不同

2.5 fseek()

  • fseek()的作用类似系统调用 lseek(), 用于设置文件读写位置偏移量
//函数原型
#include <stdio.h> 
int fseek(FILE *stream, long offset, int whence);

函数参数和返回值含义如下:

stream: FILE 指针。

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

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

返回值: 成功返回 0;发生错误将返回-1,并且会设置 errno 以指示错误原因; 与 lseek()函数的返回值 意义不同,这里要注意!

demo

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
    char buf[] = "https://www.eduvstc.cn\n";
    char buf1[12]={0};
    int size;
    FILE *fp = NULL;
    // 打开文件
    if ((fp = fopen("./a.txt", "w+")) == NULL)
    {
        perror("fopen error");
        exit(-1);
    }
    printf("文件打开成功!\n");
    // 写入数据
    if (sizeof(buf) > fwrite(buf, 1, sizeof(buf), fp))
    {
        printf("fwrite error\n");
        fclose(fp);
        exit(-1);
    }
    printf("数据写入成功!\n");

    fseek(fp,0,SEEK_SET);

    //读取数据
    if (sizeof(buf) > (size = fread(buf1, 1, sizeof(buf)), fp)))
    {
        if (ferror(fp))
        { // 使用 ferror 判断是否是发生错误
            printf("fread error\n");
            fclose(fp);
            exit(-1);
        }
        // 如果未发生错误则意味着已经到达了文件末尾 
    }
    printf("%s\n",buf1);

    // 关闭文件
    fclose(fp);
    exit(0);
}

2.6 其他读写函数

读写函数一

  • fgetc()与getc()功能完全一样,区别是fgetc是函数,而getc是宏。
  • fputc()与putc()功能完全一样,区别是fputc是函数,而putc是宏。
  • getchar()和putchar()只能针对键盘输入和屏幕输出,不能指定别的文件。

读写函数二

  • fgets() 和 gets()区别
    • fgets() 可以读取指定的任意文件,而 gets() 只能从键盘读取
    • fgets() 有内存边界判断,而 gets() 没有,因此后者是不安全的,不建议使用
    • fgets() 在任何情形下都按原样读取数据,但 gets() 会自动去除数据末尾的 ‘\n’
  • fputs() 和 puts() 区别
    • fputs() 可以将数据写入指定的任意文件,而 puts() 只能将数据输出到屏幕
    • fputs() 在任何情形下都按原样写入数据,但 puts() 会自动给写入数据的末尾加上 ‘\n’

读写函数三

  • 区别
    • fprintf( )不仅可以像printf( )一样向标准输出设备输出信息,也可以向由stream指定的任何有相应权限的文件写入数据
    • sprintf()和snprintf()都是向一块自定义缓冲区写入数据,不同的是后者第二个参数提供了这块缓冲区的大小,避免缓冲区溢出
    • fscanf( )不仅可以像scanf( )一样从标准输入设备读入信息,也可以从由stream指定的任何有相应权限的文件读入数据
    • sscanf( )从一块由s指定的自定义缓冲区中读入数据
    • 格式化定义如下

2.7 ftell()

  • ftell()可用于获取文件当前的读写位置偏移量
//函数原型
#include <stdio.h> 
long ftell(FILE *stream);

参数 stream 指向对应的文件,函数调用成功将返回当前读写位置偏移量;调用失败将返回-1,并会设置 errno 以指示错误原因

感谢阅读我的博客,如果你喜欢的话,不妨点赞收藏关注一波!

作者:小海编程心语录-CSDN博客

  • 13
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值