@bit::Shadow
✧(≖ ◡ ≖✿
目录
glibc是Linux中使用最广泛最核心的C语言标准库实现。像: printf malloc open strlen等。
模拟实现:使用open write close核心系统调用来实现fopen fwrite fclose fflush。
文件与缓冲区的关系
输入-缓冲区-文件
采用f系列接口,缓冲区是链接stdin与文件的桥梁。
模拟实现
文件属性
为描述文件属性及库函数的便捷实现,创建以struct IO_FILE类型(MyFile)结构体:
cpp
#define MAX
typedef struct IO_FILE
{
int fileNo; //fd
int flag; //打开模式:O_WRONLY、O_CREAT、O_TRUNC及O_APPEND
char outBuffer[MAX] //缓冲区字符数组
int bufferlen; //outBuffer长度
int flushMethod; //刷新方法
}MyFile;
注意:typedef的使用格式,typedef将类型"struct IO_FILE"以"MyFile"替代。
文件库函数
fopen()
原型:
FILE* fopen(const char* pathname, const char* mode);
//pathname:绝对路径/相对路径
//mode:"w" "r" "a"............
实现:
cpp
MyFile* MyFopen (const char *pathname, const char* f);
1.明确打开方式以对文件属性调整。
2.☆☆☆BuyFile()以malloc申请空间。
3.返回MyFile。
MyFile* MyFopen(const char* pathname, const char* f):
cpp
MyFile* MyFopen (const char *pathname, const char* f)
{
int fd;
int flag;
// 打开方法定位属性:
if(strcmp(f,"r")==0)
{
fd = open(pathname,O_RDONLY);
flag = O_RDONLY;
}
else if(strcmp(f,"w")==0)
{
fd = open(pathname, O_WRONLY | O_CREAT | O_TRUNC,0666);
flag = O_WRONLY | O_CREAT | O_TRUNC;
}
else if(strcmp(f,"a")==0)
{
fd = open(pathname, O_APPEND | O_CREAT, 0666);
flag = O_APPEND | O_CREAT;
}
else
{
printf("该功能未添加\n");
return NULL;
}
if(fd == -1)
{
perror("open failed!!\n");
return NULL;
}
MyFile* file = BuyFile(fd, flag, LINE_FLUSH);
if(file == NULL)
{
perror("MyFopen::BuyFile() failed\n");
return NULL;
}
return file;
}
MyFile* BuyFile(int _fileNo, int _flag, _flushMethod):
cpp
MyFile* BuyFile(int _fileNo, int _flag, int _flushMethod)
{
//空间申请!!
MyFile* newfile=(MyFile*)malloc(sizeof(MyFile));
if(newfile == NULL) return NULL;
//memset()初始化好的习惯
memset(newfile, 0, sizeof(MyFile));
//文件属性设置:
newfile->fileNo = _fileNo;
newfile->flag = _flag;
newfile->flushMethod = _flushMethod;
return newfile;
}
文件打开会不会发生缓冲区内存在内容?而需要缓冲区刷新?
缓冲区有内容<--->写入操作与接下来文件打开的要求矛盾。
fwrite()
1.传参数据拷贝到缓冲区。
☆2.写入完成后是否刷新缓冲区取决于文件打开方式flag。
cpp
size_t MyFwrite(const void *ptr, size_t size, size_t nmemb, MyFile *stream)
{
//1.拷贝到缓冲区
memcpy(stream->outBuffer, ptr, size*nmemb);
//bufferlen是字节个数还是元素个数? 肯定是字节个数因为写入文件的全部设置为字符
stream->bufferLen += size*nmemb;
//ferite的作用是写入到缓冲区还是写到文件内?明显是写入到缓冲区否则fwrite就没用了。
//要立即刷新缓冲区吗?
//刷新缓冲区的目的是拷贝缓冲区内容到文件内
//printf("%d\n",size*nmemb);
//缓冲区需要刷新的情况:
if((stream->flag & O_TRUNC || stream->flag & O_APPEND) && \
stream->outBuffer[stream->bufferLen-1]=='\n')
{
printf("缓冲区刷新成功\n");
MyFflush(stream);
}
return nmemb;
}
fflush()
fflush是程序退出/fwrite特定类型后的写入数据操作:
cpp
//刷新
int MyFflush(MyFile* stream)
{
if(stream->bufferLen <= 0) return 0;
//清除缓冲区内容到文件内
//操作系统只认fd!!
write(stream->fileNo,stream->outBuffer,stream->bufferLen);
stream->bufferLen=0;
return 0;
}
fclose()
☆☆☆清空资源前必先刷新缓冲区:
cpp
//Fclose
int MyFclose(MyFile* stream)
{
//close退出强制刷新缓冲区
MyFflush(stream);
close(stream->fileNo);
//资源释放
free(stream);
return 0;
}
感谢观看
求关注
