自学内容网 自学内容网

标准IO的缓冲区

#include <my_head.h>
int main(){
    printf("11111");
    while(1);
    return 0;
}

结果程序没有任何输出。

1. 缓冲区的类型

1. 1 缓冲区的类型

  1. 行缓存----和终端相关就是行缓存 -- 最多可存1024字节
  2. 全缓存----和文件相关就是全缓存 -- 最多可存4096字节
  3. 无缓存----stderr

1.2 缓冲区的大小

        行缓存 -- 1024

#include <my_head.h>

int main(int argc,const char *argv[]){
    int a = 0;
    fgetc(stdin);
    printf("stdin-行缓存的大小是%ld\n",stdin->_IO_buf_end - stdin->_IO_buf_base);   
    return 0;
}

        全缓存 -- 4096

#include <my_head.h>

int main(int argc,const char *argv[]){
    FILE *fp = fopen("./b.c","w+");
    if(NULL == fp){
        PRINT_ERR("fopen error");
    }

    char ch = 0;
    ch = fgetc(fp);//获取一个字符,文件中后面的4095个字符都会加载到缓冲区
    printf("缓存的大小是%ld\n",fp->_IO_buf_end - fp->_IO_buf_base);   
   
    fclose(fp);
    return 0;
}

运行结果:

无缓存 -- 0

#include <my_head.h>

int main(int argc,const char *argv[]){
    printf("1");
    perror("error");
    while(1);
    return 0;
}

1.3 缓冲区的刷新时机

  1. 程序结束会刷新
  2. 换行符会刷新缓冲区
  3. 输入输出切换会刷新缓冲区
  4. fflush会强制刷新
  5. 关闭FILE指针会刷新
  6. 缓冲区满会刷新
#include <my_head.h>

int main(int argc,const char *argv[]){
    //1.程序结束会刷新
    //printf("11111");

    //2.换行符会刷新缓冲区
    //printf("22222\n");
    //while(1);

    //3.输入输出切换会刷新缓冲区
    //printf("333");
    //int a = 0;
    //scanf("%d",&a);
    //while(1);

    //4.fflush强制刷新
    //printf("4444");
    //fflush(stdout);//刷新标准输出缓冲区
    //while(1);

    //5.关闭FILE指针会刷新
    //printf("5555");
    //fclose(stdout);
    //while(1);

    //6.缓冲区满会刷新
    for(int i = 0; i < 1025;i++){
        fputs('a',stdout);
    }
    while(1);
    
    return 0;
}

全缓存的刷新时机

  1. 程序结束会刷新
  2. 输入输出切换会刷新缓冲区
  3. fflush会强制刷新
  4. 关闭FILE指针会刷新
  5. 缓冲区满会刷新

2. 标准IO

2.1 fprintf/sprintf/snprintf 函数的使用

#include <stdio.h> -- 所需的头文件
int fprintf(FILE*stream,const char *format,...);
功能:向文件中格式化输出内容
参数:
    stream:文件指针
    format:输出格式(和printf一样)
    ...:可变参数,和printf一样
返回值:成功返回输出的字符的个数,失败返回负数

int sprintf(char *str,const char *format,...);
功能:向字符数组中格式化输出内容
参数:
    str:字符数组的首地址
    format:输出格式--和printf一样
    ...:可变参数
返回值:成功返回输出的字符个数,失败返回负数

int snprintf(char *str,size_t size,const char *format,...);
功能:向字符数组中格式化输出内容
参数:
    str:字符数组的首地址
    size:格式化输出的字符串的长度(size -1)
    format:输出格式--和printf一样
    ...:可变参数
返回值:成功返回输出的字符个数,失败返回负数

fprintf/sprintf/snprintf函数的使用示例

#include <my_head.h>

int main(int argc,const char *argv[]){
    //sprintf函数的使用
    char str_buf[128] = {0};
    char ch = 'a';
    int var1 = 100;
    char *str = "hello world";
    sprintf(str_buf,"ch = %c,var1 = %d,str = %s",ch,var1,str);
    printf("str_buf = [%s]\n",str_buf);
    //snprintf和sprintf函数使用一致,但是snprintf可以解决容易数组越界的问题
    char str_buf1[10] = {0};
    snprintf(str_buf1,sizeof(str_buf1),"ch = %c,var1 = %d,str = %s",ch,var1,str);
    printf("str_buf = [%s]\n",str_buf1);

    //fprintf函数的使用
    FILE *fp = fopen("./b.c","r+");
    if(NULL == fp)
        PRINT_ERR("fopen error");
        fprintf(fp,"ch = %c",ch);
    

    return 0;
}

运行结果:

2.2 fread/fwrite 函数的使用

#include <stdio.h>
size_t fread(void *ptr,size_t size,size_t nmemb,FILE *stream);
功能:从文件(stream)中读取nmemb*size个字节的数据到ptr
参数:
    ptr:保存读取到的数据的首地址
    size:块的大小
    nmemb:块的数量
    stream:文件指针
返回值:成功返回读取到的块的数量(如果size为1,读取到的块的数量和读取到的字节数是一样的);
    失败或者读取到的文件结尾返回小于nmemb的数组,
    int feof(FILE *stream);//如果读取到文件的结尾,这个函数会返回非0的数值
    int ferror(FILE *stream);//如果读取错误,这个函数会返回非0的数值
if(feof(fp))
    printf("读取到文件结尾\n");
if(ferror(fp))
    printf("读取错误\n");

size_t fwrite(const void *ptr,size_t size,size_t nmemb,FILE *stream);
功能:从ptr中获取数据,向文件(stream)中写入nmemb*size个字节
参数:
    ptr:保存读取到的数据的首地址
    size:块的大小
    nmemb:块的数量
    stream:文件指针
返回值:成功返回写入块的数量,失败同上

2.3 fseek/ftell/rewind 光标相关的函数

#include <stdio.h> -- 所需要的头文件
int fseek(FILE *stream,long offset,int whence);
功能:偏移文件光标
参数:
    stream:文件指针
    offset:偏移量
        大于0:向后偏移
        等于0:不偏移
        小于0:向前偏移
    whence:偏移的基地址
        SEEK_SET:从文件开头开始偏移
        SEEK_CUR: 从当前位置开始偏移
        SEEK_END: 从文件结尾开始偏移
返回值:成功返回0,失败返回-1,置位错误码

long ftell(FILE*stream);
功能:返回当前光标的位置
参数:文件指针
返回值:当前光标的位置

void rewind(FILE *stream);
功能:将光标置位到文件开头

偏移光标的使用示例

#include <my_head.h>

int main(int argc,const char *argv[]){
    //打开文件
    FILE *fp = fopen("./b.c","r+");
    if(NULL == fp){
        PRINT_ERR("fopen error");
    }
    //从当前位置向后偏移4字节
    fseek(fp,4,SEEK_CUR);
    int ch = fgetc(fp);
    printf("ch = %c\n",ch);

    //从文件结尾向前偏移
    fseek(fp,-4,SEEK_END);
    ch = getc(fp);
    printf("ch = %c\n",ch);

    //从文件开头向后偏移
    fseek(fp,10,SEEK_SET);
    ch = fgetc(fp);
    printf("ch = [%c]\n",ch);

//使用ftell获取当前光标的位置
int pos = ftell(fp);
printf("当前光标位置:%d\n",pos);

    return 0;
}

3.4 使用标准IO对bmp图片进行操作

三原色:每个像素中包含R、G、B三种颜色;

不同颜色的亮度位0~255

对于图片来说,每个像素点可以理解为由三个255的数据组成。

一个像素点占三个字节。

3、文件IO(系统调用)

3.1 文件IO的特点

文件IO又叫体统调用。

系统调用:就是受控的内核入口,我们通过系统调用和内核进行交互。

文件IO的可移植性差,效率低,实时性强。

3.2 文件描述符

在文件IO中,我们通过文件描述符去操作文件。

文件描述符本质是一个大于等于0的整数,使用open函数获取文件描述符。

每个正在运行的程序,可以拥有的文件描述符最大个数为1024,ulimit -n 2048 可以修改这个限制

每个正在运行的程序都会有三个默认打开的文件描述符。

标准输入:0

标准输出:1

标准出错:2

FILE指针和文件描述符的关系:

        FILE指针包含文件描述符。

3.3 open(打开文件)

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h> ------所需头文件

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_TRUNC:清空文件
        O_EXCL: 结合O_CREAT使用,如果文件存在会置为EEXIST错误码
mode:如果flags加上O_CREAT 选项,就需要使用此参数
        创建的文件权限:如0666
        实际创建的文件权限是0666 & (~umask)
        umask是创建文件的掩码,通过umask可以查看掩码 umask 0222 修改掩码
返回值:成功返回文件描述符(遵循最小分配原则),失败返回-1,置位错误码

使用方式:
open("./a.txt",O_RDWR|O_CREAT|O_TRUNC,0666);
r+ O_RDWR
W: O_WRONLY|O_CREAT|O_TRUNC

flags:原理,本质就是位操作

flags:这个参数的每个bit都会对应一种打开文件的模式

#include <my_head.h>

int main(int argc,const char *argv[]){
    //打开文件
    int fd;
    fd = open("./b.c",O_RDONLY);
    if(-1 == fd){
        PRINT_ERR("open error");
    }
    printf("打开文件成功,文件描述符为%d\n",fd);
    return 0;
}

运行结果:


原文地址:https://blog.csdn.net/2303_78438820/article/details/142831480

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!