在之前,我们应该都多少接触过了C语言的文件管理,fopen,fclose,fputs....等函数的用法,也分析了系统层面上C语言是如何实现文件管理的。
回顾
上一个文章,我们讲解了十分重要的知识,在文件被打开时会生成进程,而这个进程就拥有着属于它的缓冲区,而缓冲区拥有着满足各自需求的刷新策略,比如说标准输出(stdout)是遇到\n刷新。也着重讲解了文件被打开是被包含于PCB存储的struct files_struct当中。
今天,我们就来自己简单实现一个自己的MyFILE
#include<stdio.h>
#include<sys/types.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<string.h>
#include<assert.h>
typedef struct MyFILE{
int fd;
char buf[1024];
size_t end; //end代表存储的有效数据个数
}MyFILE;
MyFILE* fopen_(const char* pathname ,const char* mode)
{
assert(pathname);
assert(mode);
int fd = -1;
if(strcmp(mode,"r") == 0)
{
fd = open(pathname,O_RDONLY);
}
else if(strcmp(mode,"w") == 0)
{
fd = open(pathname,O_WRONLY|O_CREAT|O_TRUNC,0666);
}
else if(strcmp(mode,"a") == 0)
{
fd = open(pathname,O_WRONLY|O_CREAT|O_APPEND,0666);
}
if(fd < 0) return NULL;
MyFILE* newfile = (MyFILE*)calloc(0,sizeof(MyFILE));
newfile->fd = fd;
//end初始化为0,代表缓冲区没有存任何数据
newfile->end = 0;
return newfile;
}
void fclose_(MyFILE* stream)
{
assert(stream);
if(stream->end > 0)
{
write(stream->fd,stream->buf,strlen(stream->buf));
}
close(stream->fd);
}
void fputs_(const char* string, MyFILE* stream)
{
assert(stream);
assert(string);
//往缓冲区添加数据
strcpy(stream->buf+stream->end,string);
stream->end += strlen(string);
if(stream->fd == 1)
{
//标准输出 行刷新策略
if(stream->buf[stream->end-1] == '\n')
{
//for degug
printf("fflush: %s\n",stream->buf);
write(stream->fd,stream->buf,strlen(stream->buf));
stream->end = 0;
}
}
else if(stream->fd == 0)
{
//标准输入 视为普通文件即可
}
else
{
//普通文件
}
}
void fgets_(MyFILE* stream , char* string)
{
assert(stream);
assert(string);
strncpy(string,stream->buf,stream->end);
if(sizeof(string) > stream->end)
{
*(string+stream->end) = '\0';
}
else{
*(string+sizeof(string)-1) = '\0';
}
}
int main(int argc, const char* argv[])
{
MyFILE* file1 = fopen_("log.txt","w");
char str1[128] = "hello world\n";
fputs_(str1,file1);
fclose_(file1);
return 0;