Day 30 标准IO
作者:mmseoamin日期:2024-02-22

文章目录

  • 1.什么是标准IO
    • 1.1 概念
    • 1.2 特点
    • 1.3 操作
    • 2.缓存区
    • 3.函数接口
      • 3.1 打开文件fopen
      • 3.2 关闭文件 fclose
      • 3.3 读写文件操作
        • 3.3.1 每次读写一个字符:fgetc()、fputc()
          • 每次读一个字符fgetc()
          • 每次写一个字符fputc()
          • (1)针对文件
          • (2)针对终端
          • feof和ferror
          • 3.3.2 每次一串字符的读写fgets()和fputs()
            • char * fgets(char *s, int size, FILE * stream);
            • int fputs(const char *s, FILE *stream);
            • (1)针对终端
            • (2)针对文件
            • 3.3.3 二进制读写fread()和fwrite()
              • size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
              • size_t fwrite(const void *ptr, size_t size, size_t nmemb,

                1.什么是标准IO

                1.1 概念

                标准IO:在c库中定义的一组专门用于输入输出的函数

                Day 30 标准IO,在这里插入图片描述,第1张

                1.2 特点

                (1)通过缓冲机制减少系统调用,提高效率

                系统调用:内核向上(用户)提供的一组接口

                例如:从硬盘读1kb数据每次只能读1b

                Day 30 标准IO,在这里插入图片描述,第2张

                若将数据先存入缓存区则可以减少硬件到用户层的调用次数

                (2)围绕着流(stream)进行操作,流用FILE*来描述

                注意: vi用ctags索引使用:

                1)vi -t 查找名称

                输入前面序号,回车。

                2)继续追踪:

                将光标定位到要追踪的内容,ctrl+]

                回退:ctrl+t

                3)跳转到上次位置:ctrl+o

                跳转到下次位置:ctrl+i

                (3) 标准IO默认打开三个流,sdtin(标准输入)、stdout(标准输出)、stderr(标准错误)

                1.3 操作

                打开文件:fopen

                关闭文件: fclose

                读写操作:fgetc、fputc、fgets、fputs、fread、fwrite

                其他:freopen、rewind、fseek

                2.缓存区

                (1)全缓存:和文件相关的

                (2)行缓存:和终端相关

                刷新缓存区

                条件一:\n(换行)

                条件二:程序退出

                条件三:fflush(NULL)(强制刷新所有缓存区) fflush(stdout)(刷新输出缓存区)

                条件四:缓存区满

                (3)不缓存,没有缓存,标准错误。

                综上:当我们每次要打印数据时,并不是将数据直接发送给标准输出设备,也就是并直接发送给显示器,而是将要打印的数据先存放到缓存区,当缓冲存数据满时,或者遇到\n,或者程序结束时,或者手动刷新缓存区时,缓冲区才会把数据传输到标准输出设备中,也就是显示器中进行输出。

                练习:计算标准输出缓存区大小 KB

                方法一:利用循环打印展示

                Day 30 标准IO,在这里插入图片描述,第3张

                方法二:利用结构体指针 stdout (流指针FILE*类型)

                #include
                int main(int argc, char const *argv[])
                {
                    printf("buf:"); //不进行输出的话缓存区不会开辟,所以要先加一句打印为了让标准IO开辟输出缓存区。
                    printf("%d\n",stdout->_IO_buf_end - stdout->_IO_buf_base);
                    return 0;
                }
                

                得到1024B

                3.函数接口

                3.1 打开文件fopen

                FILE *fopen(const char *path, const char *mode);

                功能:打开文件

                参数:

                path:打开的文件路径

                mode:打开的方式

                r:只读,当文件不存在时报错,文件流定位到文件开头

                r+:可读可写,当文件不存在时报错,文件流定位到文件开头

                w:只写,文件不存在创建,存在则清空

                w+:可读可写,文件不存在创建,存在则清空

                a:追加(在末尾写),文件不存在创建,存在追加,文件流定位到文件末尾

                a+:读和追加,文件不存在创建,存在追加,读文件流定位到文件开头,写文件流定位到文件末尾

                注:当a+的方式打开文件时,写只能在末尾进行追加,定位操作是无法改变写的位置,但是可以改变读的位置

                返回值:

                成功:文件流

                失败:NULL,并且会设置错误码

                3.2 关闭文件 fclose

                #include 
                int main(int argc, char const *argv[])
                {
                    FILE *fp;
                    //1.打开文件
                    fp = fopen("test.c", "r");
                    if (NULL == fp)
                    {
                        perror("fopen err");
                        //while(1);//标准错误是不缓存,所以会直接显示到终端
                        return -1;
                    }
                    printf("fopen success\n");
                    //2. 关闭文件
                    fclose(fp);
                    return 0;
                }
                

                3.3 读写文件操作

                3.3.1 每次读写一个字符:fgetc()、fputc()

                每次读一个字符fgetc()

                int fgetc(FILE * stream);

                功能:从文件中读取一个字符,并将当前文件指针位置向后移动一个字符。

                参数:stream:文件流

                返回值:

                成功:读到的字符

                失败或读到文件末尾:EOF(-1)

                每次写一个字符fputc()

                int fputc(int c, FILE *stream);

                功能:向文件中写入一个字符, 成功写入后文件指针会自动向后移动一个字节位置。

                参数:c:要写的字符

                stream:文件流

                返回值:成功:写的字符的ASCII

                失败:EOF(-1)

                (1)针对文件

                fgetc(fp)

                fputc(‘字符’,fp)(注意修改权限)

                (2)针对终端

                fgetc(stdin)

                fpuc(‘字符’,stdout)

                feof和ferror

                int feof(FILE * stream);

                功能:判断文件有没有到结尾,也就是当前所在位置后面还有没有字符。

                返回:如果到达文件末尾,返回非零值。如果后面还有字符则返回0。

                int ferror(FILE * stream);

                功能:检测文件有没有出错

                返回:文件出错,返回非零值。如果没有出错,返回0。

                3.3.2 每次一串字符的读写fgets()和fputs()

                char * fgets(char *s, int size, FILE * stream);

                功能:从文件中每次读取一行字符串

                参数:

                s:存放字符串的地址

                size:一次读取的字符个数

                stream:文件流

                返回值:

                成功:s的地址

                失败或读到文件末尾:NULL

                特性: 每次实际读取的字符个数为size-1个,会在末尾自动添加\0

                每次读一行,遇到\n或者到达文件末尾后不再继续读下一行

                并把它存储在s所指向的字符串内。

                如果到达末尾则返回NULL,继续输出的还是上一次buf中保留的内容。

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

                功能:向文件中写字符串

                参数:s:要写的内容

                stream:文件流

                返回值:成功:非负整数

                失败:EOF

                (1)针对终端

                char buf[32]=“”;

                fgets(buf,sizeof(buf),stdin);

                printf(“buf:%s\n”,buf);

                (2)针对文件

                char buf[32]=“”;

                fgets(buf,sizeof(buf),fp);

                fputs(buf,fp);

                3.3.3 二进制读写fread()和fwrite()

                size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

                功能:从文件流读取多个元素(将二进制数据从文件读出)

                参数: ptr :是一个指针,是存放数据的存储空间的起始地址,用来存放读取元素

                size :元素大小 sizeof(元素数据类型)

                nmemb :读取元素的个数

                stream :要读取的文件流

                返回值:成功:读取的元素的个数

                读到文件尾或失败: 0

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

                功能:将二进制数据写入文件

                参数: ptr :是一个指针,保存要输出数据的空间的地址。

                size :要写入的字节数 sizeof(数据类型)

                nmemb : 要进行写入元素的个数

                stream: 目标文件流指针

                返回值:成功:写的元素个数

                失败 :-1

                文件定位操作:rewind(FILE *fp);