【LeetCode】模拟实现FILE以及认识缓冲区

模拟实现FILE以及认识缓冲区

      • 刷新缓冲逻辑图
      • 自定义实现
      • 如何强制刷新内核缓冲区
      • 例子

刷新缓冲逻辑图

在这里插入图片描述

自定义实现

mystdio.h
#pragma once 
#include <stdio.h>

#define NUM 1024
#define BUFF_NOME 0x1
#define BUFF_LINE 0x2
#define BUFF_ALL 0x4

typedef struct _MY_FILE
{
  int fd;//接受描述符的值
  int flags;//用来记录打开方式
  char outputbuffer[NUM];//缓冲区保存
  int current;//记录缓冲区有多少字符
}MY_FILE;

MY_FILE* my_fopen(const char* path,const char* mode);
size_t my_fwrite(const void* ptr,size_t size,size_t nmemb,MY_FILE* stream);
int my_fclose(MY_FILE* fp);
int my_fflush(MY_FILE* fp);
mystdio.c
#include "mystdio.h"
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>

MY_FILE* my_fopen(const char* path,const char* mode)
{
  //1.识别标志位,打开方式
  int flag = 0;
  if(strcmp(mode,"r") == 0) flag |= O_RDONLY;
  else if(strcmp(mode,"w") == 0) flag |= (O_CREAT | O_WRONLY | O_TRUNC);
  else if(strcmp(mode,"a") == 0) flag |= (O_CREAT | O_WRONLY | O_APPEND);
  else if(strcmp(mode,"r+") == 0) flag |= (O_WRONLY | O_RDONLY);
  else if(strcmp(mode,"w+") == 0) flag |= (O_CREAT | O_WRONLY | O_RDONLY | O_TRUNC);
  else if(strcmp(mode,"a+") == 0) flag |=(O_CREAT | O_WRONLY | O_RDONLY | O_APPEND);
  //2.尝试打开文件
  mode_t m = 0666;
  int fd = 0;
  if(flag | O_CREAT)
  {
    fd = open(path,flag,m);
  }
  else 
  {
    fd = open(path,flag);
  }

  if(fd < 0) return NULL;

  //3.给用户返回MY_FILE对象,需要先进行构建
  MY_FILE *mf = (MY_FILE*)malloc(sizeof(MY_FILE));
  if(mf == NULL)
  {
    close(fd);
    return NULL;
  }

  //4.初始化MY_FILE对象
  mf->fd = fd;
  mf->flags = 0;
  mf->flags |= BUFF_LINE;
  memset(mf->outputbuffer,'\0',sizeof(mf->outputbuffer));
  mf->current = 0;

  //5.返回打开的文件
  return mf;
}

//冲刷缓冲区
int my_fflush(MY_FILE* fp)
{
  assert(fp);
  //将用户缓冲区的数据,通过系统调用接口,冲刷给os
  write(fp->fd,fp->outputbuffer,fp->current);
  fp ->current = 0;

  //fsync(fp-fd);
  return 0;
}

//这里返回的是字节数,不是模拟实现的输入的、个数nmemb
size_t my_fwrite(const void* ptr,size_t size,size_t nmemb,MY_FILE* stream)
{
  //1、缓冲区如果已经满了,就直接写入
  if(stream->current == NUM)my_fflush(stream);

  //2.根据缓冲区剩余情况,进行数据拷贝即可
  size_t user_size = size * nmemb;
  size_t my_size = NUM - stream->current;

  size_t write = 0;
  if(my_size >= user_size) 
  {
    memcpy(stream->outputbuffer + stream->current,ptr,user_size);
   //3.更新计数器字段
    stream->current += user_size;
    write = user_size;
  }
  else 
  {
    //如果缓冲区内存不够存放的话,指挥存放它的最大值
    memcpy(stream->outputbuffer+stream->current,ptr,my_size);
    stream->current += my_size;
    write = my_size;
  }
  //4.开始计划刷新,他们高效体现在哪里? --- TODO
  //不发生刷新的本质,不进行写入,就是不进行IO,不进行调用系统调用,所以my_fwrite函数调用会非常快,数据会暂时保存在缓冲区中
  //可以在缓冲区中挤压多份数据,统一进行刷新写入,本质:就是一次IO可以IO更多的数据,提高IO效率
  if(stream->flags & BUFF_ALL)
  {
    if(stream->current == NUM) my_fflush(stream);
  }
  else if(stream->flags & BUFF_LINE)
  {
    if(stream->outputbuffer[stream->current-1] =='\n')
    {
      my_fflush(stream);
    }
  }
  else 
  {
    //TODO
  }
  return write;
}


int my_fclose(MY_FILE* fp)
{
  assert(fp);
  //1.冲刷缓冲区
  if(fp->current > 0) my_fflush(fp);

  //2.关闭文件
  close(fp->fd);

  //3.释放堆空间
  free(fp);

  //4.指针置NULL --- 可以设置
  fp = NULL;

  return 0;
}
main.c
#include "mystdio.h"
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#define MYFILE "log.text"
int main()
{
  MY_FILE* fp = my_fopen(MYFILE,"w");
  if(fp == NULL) return 1;

  const char* str = "hello my my_fwrite";
  int cnt = 10;
  //操作文件
  while(cnt)
  {
    char buffer[1024];
    snprintf(buffer,sizeof(buffer),"%s:%d\n",str,cnt--);
    size_t size = my_fwrite(buffer,strlen(buffer),1,fp);
    sleep(1);
    printf("当前成功写入:%lu个字节\n",size);
  }
    my_fclose(fp);

    return 0;
}

如何强制刷新内核缓冲区

根据文件描述符进行强制刷新

main.c
#include "mystdio.h"
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#define MYFILE "log.text"
int main()
{
  MY_FILE* fp = my_fopen(MYFILE,"w");
  if(fp == NULL) return 1;

  const char* str = "hello my my_fwrite";
  int cnt = 10;
  //操作文件
  while(cnt)
  {
    char buffer[1024];
    snprintf(buffer,sizeof(buffer),"%s:%d\n",str,cnt--);
    if(cnt % 5 == 0)
    {
    	//当cnt是五的倍数的时候就会强制刷新一次
    	my_fwrite(buffer,strlen(buffer),1,fp);
    }
  }
    my_fclose(fp);

    return 0;
}

在这里插入图片描述

例子

像我们进行scanf输入的时候,其实本身我们输入的是一串字符串,将这个字符串读入对应的缓冲区buff后,然后通过分解工作,进一步传入系统,系统,系统在通过一些指令输入输出想要的结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/87165.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ChatGPT-4: 半年的深度使用思考

几个月的时间一直在使用 ChatGpt-4&#xff0c;以口述语音转文字的形式说一下自己的体会。 1、选择版本 大前提&#xff1a;我使用的都是 GPT4 的版本。也就是说至少每个月要付费20$。 因为 3.5 的版本&#xff0c;实际上使用体验是非常差的&#xff0c;主要体现在答非所问上。…

c++ 命名空间

1. 基本概念  1.1 定义与使用  1.2 using语句2. 进阶语法  2.1 内嵌名字空间  2.2 扩展性  2.3 全局作用域3. 小结 1. 基本概念 名字空间本质上是自定义作用域&#xff0c;由于C设计的初衷是开发大规模软件&#xff0c;大量的软件库必然会加剧全局符号&#xff08;变量、…

Word中对象方法(Methods)的理解及示例(上)

【分享成果&#xff0c;随喜正能量】奋斗没有终点,任何时候都是一个起点&#xff0c;沉潜是为了蓄势待发&#xff0c;沉潜是为了等待因缘。鲸豚沉潜于大海&#xff0c;幽兰深藏于山谷&#xff0c;能够经得起沉潜的人&#xff0c;才会有更高的成就。正如一年的树木只能当柴烧&am…

PPPoE vs 静态:网络中的最佳选择

在企业网络中&#xff0c;选择适合的网络连接方式对于网络性能和安全至关重要。今天我将和大家分享关于PPPoE和静态IP地址的知识&#xff0c;探讨它们在企业网络中的优劣和最佳选择。本文将为您提供详细的分析和解决方案&#xff0c;帮助您在选择网络连接方式时做出明智的决策。…

Jmeter常用线程组设置策略

一、前言 ​ 在JMeter压力测试中&#xff0c;我们时常见到的几个场景有&#xff1a;单场景基准测试、单场景并发测试、单场景容量测试、混合场景容量测试、混合场景并发测试以及混合场景稳定性测试 在本篇文章中&#xff0c;我们会用到一些插件&#xff0c;在这边先给大家列出&…

小兔鲜儿 - 推荐模块

目录 动态获取数据 静态结构 获取页面参数​ 获取数据​ 类型声明 热门推荐 – 渲染页面和Tab交互 热门推荐 – 分页加载 热门推荐 – 分页条件 type 和 interface 的区别 type 和 interface 的相似之处 type 的特点和用途 interface 的特点和用途 何时使用 type…

数据结构:直接插入排序,希尔排序,选择排序,堆排序,冒泡排序,快速排序,归并排序,计数排序(C实现)

个人主页 &#xff1a; 个人主页 个人专栏 &#xff1a; 《数据结构》 《C语言》 文章目录 前言一、插入排序1.直接插入排序2.希尔排序 二、选择排序1. 选择排序2.堆排序 三、交换排序1.冒泡排序2.快速排序(递归)a.hoare版(PartSort1)b.挖坑法(PartSort2)c.前后指针法(PartSort…

【云驻共创】华为云之手把手教你搭建IoT物联网应用充电桩实时监控大屏

文章目录 前言1.什么是充电桩2.什么是IOT3.什么是端、边、云、应用协同4.什么是Astro轻应用 一、玩转lOT动态实时大屏&#xff08;线下实际操作&#xff09;1.Astro轻应用说明1.1 场景说明1.2 资费说明1.3 整体流程 2.操作步骤2.1 开通设备接入服务2.2 创建产品2.3 注册设备2.4…

vue页面转pdf后分页时文字被横向割裂

效果 预期效果 //避免分页被截断async outPutPdfFn (id, title) {const _t this;const A4_WIDTH 592.28;const A4_HEIGHT 841.89;// dom的id。let target document.getElementById(pdf);let pageHeight target.scrollWidth / A4_WIDTH * A4_HEIGHT;// 获取分割dom&#xf…

static相关知识点详解

文章目录 一. 修饰成员变量二. 修饰成员方法三. 修饰代码块四. 修饰类 一. 修饰成员变量 static 修饰的成员变量&#xff0c;称为静态成员变量&#xff0c;该变量不属于某个具体的对象&#xff0c;是所有对象所共享的。 public class Student {private String name;private sta…

MySQL-Centos下MySQL5.7安装教程

MySQL安装教程 一&#xff0c;卸载MySQL二&#xff0c;安装MySQL三&#xff0c;mysql登录四&#xff0c;修改配置文件 一&#xff0c;卸载MySQL 1.如果你的机器上mysqld服务器还在运行&#xff0c;那么第一步就是要停掉服务。 systemctl stop mysqld;2.查看系统中安装的关于m…

vim 常见操作

Vim 工作模式 1、vim 三种基本的工作模式 vim有三种基本的工作模式&#xff0c;分别为&#xff1a;命令模式、末行模式、编辑模式。关于这三种工作模式的介绍&#xff0c;请见下文。 1.1、命令模式 使用vim打开文件之后&#xff0c;首先进入命令模式&#xff0c;它是vim编辑…

RISC-V公测平台发布· CoreMark测试报告

一. CoreMark简介 CoreMark是一款用于评估CPU性能的基准测试程序&#xff0c;它包含了多种不同的计算任务&#xff0c;包括浮点数、整数、缓存、内存等方面的测试。CoreMark的测试结果通常被用来作为CPU性能的参考&#xff0c;它可以帮助开发人员和系统管理员评估不同处理器和…

iOS 如何对整张图分别局部磨砂,并完全贴合

官方磨砂方式 - (UIVisualEffectView *)effectView{if(!_effectView){UIBlurEffect *blur [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];_effectView [[UIVisualEffectView alloc] initWithEffect:blur];}return _effectView; }使用这种方式对一张图的上半部分和…

数学建模大全及优缺点解读

分类模型 1、距离聚类&#xff08;系统聚类&#xff09;&#xff08;常用&#xff0c;需掌握&#xff09; 优点&#xff1a; ①将一批样本数据按照他们在性质上的亲密程度在没有先验知识的情况下自动进行分类 ②是一种探索性的分析方法&#xff0c;分类结果不一定相同 例如&am…

住宅IP:解锁更快速、稳定的互联网,你准备好了吗?

随着互联网的广泛普及&#xff0c;我们对网络的需求也越来越高。无论是工作、学习还是娱乐&#xff0c;我们都希望能够享受到更快速、稳定的互联网连接。而在实现这一目标的过程中&#xff0c;住宅IP正逐渐崭露头角&#xff0c;成为了一种备受关注的解决方案。那么&#xff0c;…

用户端Web自动化测试-L2

目录&#xff1a; 高级定位-css高级定位-xpath显式等待高级使用高级控件交互方法网页 frame 与多窗口处理文件上传&#xff0c;弹框处理自动化关键数据记录电子商务产品实战 1.高级定位-css css 选择器概念 css 选择器有自己的语法规则和表达式css 定位通常分为绝对定位和相…

Java IO流(四)Netty理论[模型|核心组件]

概述 Netty是由JBOSS提供的一个Java开源框架,可从Github获取独立项目Netty是一个异步的、基于事件驱动的网络应用框架,用于快速开发可维护、高性能的网络服务器和客户端(摘录官网)Netty所谓的异步是针对用户使用Channel进行IO操作,会立即返回ChannelFuture。但IO操作的任务是提…

开源容灾备份软件,开源cdp备份软件

数据的安全性和完整性面临着硬件问题、黑客攻击、人为错误等各种威胁。在这种环境下&#xff0c;开源容灾备份软件应运而生&#xff0c;通过提供自动数据备份和恢复&#xff0c;有效地保证了公司的数据安全。 一、开源容灾备份软件的定义和作用 开源容灾备份软件是一种基于开源…

SqlServer2019—解决SQL Server 无法连接127.0.0.1的问题

1、打开SQL Server 2019配置管理器 2、SQL Servere 网络配置(启用 Named Pipes 和 TCP/IP) 3、修改TCP/IP协议(右键选择属性—IP地址)&#xff0c;具体如下图所示&#xff1a; 4、重启SQL Server服务