第3章 文件I/O(8)_贯穿案例:构建标准IO函数库
9. 贯穿案例:构建标准IO函数库
//mstdio.h
#ifndef __MSTDIO_H__
#define __MSTDIO_H__
#include <unistd.h>
#define MEOF -1 //定义文件末尾标志
//文件读写模式
enum mode{READ, WRITE, APPEND};
//MFILE结构体
typedef struct
{
int _fd;
char* _buffer; //缓冲区
char* _nextc; //下一个字符
int _mode; //读写模式
off_t _left; //剩余多少字节(对于读表示缓冲区中未读的
//字节数对于写,表示缓冲区还剩的空闲空间)
}MFILE, *PMFILE;
extern MFILE* mfopen(const char* const pathname, const char* const mode);
extern int mfclose(MFILE* fp);
extern void mfflush(MFILE* fp);
extern MFILE* mfdopen(int fd, const char* const mode);
extern int mfgetc(MFILE* fp);
extern int mfputc(int character, MFILE* fp);
extern int mungetc(int character, MFILE* fp);
extern char* mfgets(char* buff, int size, MFILE* fp);
extern int mfputs(char* buff, MFILE* fp);
extern size_t mfread(void* buff, size_t size, size_t counter, MFILE* fp);
extern size_t mfwrite(void* buff, size_t size, size_t counter, MFILE* fp);
#endif
//mstdio.c
#include "mstdio.h"
#include <assert.h>
#include <string.h>
#include <fcntl.h>
#include <malloc.h>
#define BUFFER_LEN 1024
MFILE* mfopen(const char* const pathname, const char* const mode)
{
int fd;
if(!strcmp(mode, "r")){
fd = open(pathname, O_RDONLY);
}else if(!strcmp(mode, "w")){
fd = open(pathname, O_WRONLY | O_CREAT | O_TRUNC, 0777);
}else if(!strcmp(mode, "a")){
fd = open(pathname, O_WRONLY | O_CREAT | O_APPEND, 0777);
}else{
return NULL;
}
if (fd < 0) return NULL;
return mfdopen(fd, mode);
}
int mfclose(MFILE* fp)
{
mfflush(fp); //先刷新缓存
int ret = close(fp->_fd);
free(fp->_buffer);
free(fp);
return ret;
}
void mfflush(MFILE* fp)
{
if(fp->_mode = READ){
fp->_nextc = fp->_buffer;
fp->_left = 0;
}else{ //WRITE or APPEND
write(fp->_fd, fp->_buffer, (BUFFER_LEN - fp->_left));
fp->_nextc = fp->_buffer;
fp->_left = BUFFER_LEN;
}
}
MFILE* mfdopen(int fd, const char* const mode)
{
MFILE* fp = (MFILE*)malloc(sizeof(MFILE));
assert( fp != NULL); //断言fp存在
fp->_buffer = (char*)malloc(BUFFER_LEN); //创建缓冲区
assert(fp->_buffer != NULL);
fp->_fd = fd;
fp->_nextc = fp->_buffer; //初始化,指向缓冲区开始处
if(!strcmp(mode, "r")){
fp->_mode = READ;
fp->_left = 0; //缓冲区剩余0字节未读取,即全部读完。
}
if(!strcmp(mode, "w")){
fp->_mode = WRITE;
fp->_left = BUFFER_LEN; //缓冲区剩BUFFER_LEN未写,即空的
}
if(!strcmp(mode, "a")){
fp->_mode = APPEND;
fp->_left = BUFFER_LEN;
}
return fp;
}
int mfgetc(MFILE* fp)
{
assert(fp->_mode == READ); //只允许读操作
//当缓存中的数据己读取完毕,先从文件中读取一批新的数据
//存入缓存中
if (fp->_left == 0){
ssize_t size = read(fp->_fd, fp->_buffer, BUFFER_LEN);
assert( size >=0 );
if(size == 0) return MEOF;
fp->_nextc = fp->_buffer;
fp->_left = size;
}
char c = *(fp->_nextc);
fp->_nextc++;
fp->_left--;
return c;
}
int mfputc(int character, MFILE* fp)
{
assert(fp->_mode == WRITE || fp->_mode == APPEND);
//若缓存己满,则先将缓存中的数据写入到文件中
if(fp->_left == 0){
if(write(fp->_fd, fp->_buffer, BUFFER_LEN) != BUFFER_LEN){
return 0;
}
fp->_nextc = fp->_buffer;
fp->_left = BUFFER_LEN;
}
*(fp->_nextc) = (char)character;
fp->_nextc++;
fp->_left--;
return 1; //返回成功写入的字符个数
}
int mungetc(int character, MFILE* fp)
{
int ret = 0;
return ret;
}
char* mfgets(char* buff, int size, MFILE* fp)
{
char* ret = NULL;
return ret;
}
int mfputs(char* buff, MFILE* fp)
{
int ret = 0;
return ret;
}
size_t mfread(void* buff, size_t size, size_t counter, MFILE* fp)
{
size_t ret = 0;
return ret;
}
size_t mfwrite(void* buff, size_t size, size_t counter, MFILE* fp)
{
size_t ret = 0;
return ret;
}
//mstdio_test.c
#include "mstdio.h"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
int main(int argc, char* argv[])
{
MFILE* fp1 = mfopen("/etc/passwd", "r");
assert(fp1 != NULL);
MFILE* fp2 = mfopen("mypasswd", "w");
assert( fp2 != NULL);
char c;
while((c=mfgetc(fp1)) != MEOF){
mfputc(c, fp2);
}
mfclose(fp1);
mfclose(fp2);
return 0;
}

浙公网安备 33010602011771号