基于C语言的内存文件实现

来源:互联网 发布:淘宝买家秀图片对比 编辑:程序博客网 时间:2024/05/21 09:52

在有些应用场景中,设备并没有磁盘设备,因此不能像PC机上那样使用标准C库的文件操作APIs,但又希望能实现一些文件操作。或者有时候在网上下载的一些应用库,这些库里应用到了文件操作APIs,但是移植的目标机器上又不具有磁盘设备。
为了实现在内存中模拟出文件的操作函数,下面将贴出部分代码,可实现基本功能:
memfile.h 文件

/** memfile.h** Copyright (C) 2017-2027, Albert.song.** This document provides a memory file interface, easy to store files in * memory rather than disk, some applications do not need to output data * to disk, so the available memory file instead.*/#ifndef _MEMFILE_H__#define _MEMFILE_H__#include "jmorecfg.h"#include <malloc.h>#include <string.h>#define MAX_FAILNAME    256#define FILENODESIZE    4096#define MSEEK_CUR    1#define MSEEK_END    2#define MSEEK_SET    0struct MFileNode{    char   lpBuffer[FILENODESIZE];    struct MFileNode *next;};typedef struct {    char   *filename;    INT32   offset;    INT32   data_length;    struct MFileNode *header;} MEMFILE;#define M_Malloc(size_len)  malloc((size_t)(size_len))  #define M_Free(ptr)         free((void*)(ptr))#define M_Memcpy(to,from,count)  memcpy((void*)(to),(void*)(from),(size_t)(count))MEMFILE *mopen(const char * filename, const char * mode);int mclose(MEMFILE *stream);int mflush(MEMFILE *stream);size_t mwrite(void* buf, size_t size, size_t count, MEMFILE *stream);size_t mread(void* buf, size_t size, size_t count, MEMFILE *stream);int mseek(MEMFILE *stream, long int offset, int origin);#endif

memfile.c 文件

/** memfile.c** Copyright (C) 2017-2027, Albert.song.** This document provides a memory file interface, easy to store files in* memory rather than disk, some applications do not need to output data* to disk, so the available memory file instead.*//* this is not a core library module, so it doesn't define JPEG_INTERNALS */#include    "memfile.h"#define NULL    ((void*)0)static int _mstrlen(const char *str,int max){    int i = 0;    for (i = 0; i < max; i++)    {        if (0 == str[i]){            break;        }    }    return i;}static char *_mstrcpy(char *str1, const char *str2){    char * s1;    s1 = str1;    while (*str2 != '\0'){        *str1++ = *str2++;    }    *str1++ = *str2++;    return s1;}static char *_mGetFileCurentPtr(size_t *remain, struct MFileNode **curnode, MEMFILE *stream){    struct MFileNode *node = NULL;    struct MFileNode *next = NULL;    UINT8 * ptr;    size_t cnt = stream->offset / FILENODESIZE + 1;    next = stream->header;    while (cnt && NULL != next){        node = next;        next = node->next;        cnt--;    }    if (node == NULL)        return NULL;    cnt = stream->offset % FILENODESIZE;    ptr = node->lpBuffer + cnt;    *remain = FILENODESIZE - cnt;    if (curnode)        *curnode = node;    return ptr;}static struct MFileNode* _mAddNode(MEMFILE *stream){    struct MFileNode *node = NULL;    struct MFileNode *next = NULL;    struct MFileNode *ptr = NULL;    ptr = (struct MFileNode *)M_Malloc(sizeof(struct MFileNode));    if (NULL == ptr){        return NULL;    }    ptr->next = NULL;    if (NULL == stream->header){        stream->header = ptr;    }    else{        next = stream->header;        while (NULL != next){            node = next;            next = node->next;        }        node->next = ptr;    }    return ptr;}MEMFILE *mopen(const char * filename, const char * mode){    MEMFILE *mFile;    int len;    mFile = M_Malloc(sizeof(MEMFILE));    if (NULL == mFile){        return mFile;    }    len = _mstrlen(filename, MAX_FAILNAME);    mFile->filename = (UINT8 *)M_Malloc((len + 2)*sizeof(char));    if (NULL == mFile->filename){        M_Free(mFile);        return NULL;    }    _mstrcpy(mFile->filename, filename);    mFile->data_length = 0;    mFile->offset = 0;    mFile->header = NULL;    return mFile;}int mflush(MEMFILE *stream){    return 0;}int mclose(MEMFILE *stream){    struct MFileNode *node;    struct MFileNode *next;    mflush(stream);    next = stream->header;    while (NULL != next){        node = next;        next = node->next;        M_Free(node);    }    M_Free(stream->filename);    M_Free(stream);    return 0;}size_t mwrite(void* buf, size_t size, size_t count, MEMFILE *stream){    size_t remain;    struct MFileNode    *node;    char           * CurPtr;    size_t         copy_len;    size_t          totall;    totall = size * count;    CurPtr = _mGetFileCurentPtr(&remain,NULL, stream);    if (NULL == CurPtr){        node =  _mAddNode(stream);        if (NULL == node)            return -1;        CurPtr = node->lpBuffer;        remain = FILENODESIZE;    }    while (totall){        copy_len = totall < remain ? totall : remain;        M_Memcpy(CurPtr, buf, copy_len);        totall -= copy_len;        remain -= copy_len;        CurPtr += copy_len;        stream->offset += copy_len;        stream->data_length += copy_len;        buf = (void*)((char*)buf + copy_len);        if (0 == remain){            node = _mAddNode(stream);            if (NULL == node){                totall = size * count - totall;                return totall/size;            }             CurPtr = node->lpBuffer;            remain = FILENODESIZE;        }    }    return count;}size_t mread(void* buf, size_t size, size_t count, MEMFILE *stream){    char           * CurPtr;    struct MFileNode    *node;    size_t          remain;    size_t          dataless;    size_t          totall;    size_t         copy_len;    totall = size * count;    CurPtr = _mGetFileCurentPtr(&remain, &node, stream);    while (totall){        dataless = stream->data_length - stream->offset;        if (dataless < remain){            remain = dataless;        }        copy_len = totall < remain ? totall : remain;        M_Memcpy(buf, CurPtr, copy_len);        stream->offset += copy_len;        totall -= copy_len;        buf = (void*)((char*)buf + copy_len);        CurPtr += copy_len;        remain -= copy_len;        dataless -= copy_len;        if (0 == dataless){            totall = size * count - totall;            return totall / size;        }        if (0 == remain){            node = node->next;            if (NULL == node){                totall = size * count - totall;                return totall / size;            }            CurPtr = node->lpBuffer;            remain = FILENODESIZE;        }    }    totall = size * count - totall;    return totall / size;}int mseek(MEMFILE *stream, long int offset, int origin){    switch (origin){        case MSEEK_CUR:stream->offset += offset; break;        case MSEEK_END:stream->offset = stream->data_length + offset; break;        case MSEEK_SET:stream->offset = offset; break;        default:return -1;    }    if (stream->offset > stream->data_length){        stream->offset = stream->data_length;    }    return 0;}

后续继续添加修改
写于:2017/03/14 下午18:20
分割线——————————————————————————————
优化读写后
memfile.h文件

/** memfile.h** Copyright (C) 2017-2027, Albert.song.** This document provides a memory file interface, easy to store files in * memory rather than disk, some applications do not need to output data * to disk, so the available memory file instead.*/#ifndef _MEMFILE_H__#define _MEMFILE_H__#include "jmorecfg.h"#include <malloc.h>#include <string.h>#define MAX_FAILNAME    256#define FILENODESIZE    4096#define MSEEK_CUR    1#define MSEEK_END    2#define MSEEK_SET    0struct MFileNode{    char   lpBuffer[FILENODESIZE];    struct MFileNode *next;};typedef struct {    char   *filename;    INT32   offset;    INT32   data_length;    INT32   remain;    char   *curptr;    struct MFileNode *header;    struct MFileNode *curnode;    struct MFileNode *endnode;} MEMFILE;#define M_Malloc(size_len)  malloc((size_t)(size_len))  #define M_Free(ptr)         free((void*)(ptr))#define M_Memcpy(to,from,count)  memcpy((void*)(to),(void*)(from),(size_t)(count))MEMFILE *mopen(const char * filename, const char * mode);int mclose(MEMFILE *stream);int mflush(MEMFILE *stream);int merror(MEMFILE *stream);size_t mwrite(void* buf, size_t size, size_t count, MEMFILE *stream);size_t mread(void* buf, size_t size, size_t count, MEMFILE *stream);int mseek(MEMFILE *stream, long int offset, int origin);#endif

memfile.c文件

/** memfile.c** Copyright (C) 2017-2027, Albert.song.** This document provides a memory file interface, easy to store files in* memory rather than disk, some applications do not need to output data* to disk, so the available memory file instead.*//* this is not a core library module, so it doesn't define JPEG_INTERNALS */#include    "memfile.h"#define NULL    ((void*)0)static int _mstrlen(const char *str,int max){    int i = 0;    for (i = 0; i < max; i++)    {        if (0 == str[i]){            break;        }    }    return i;}static char *_mstrcpy(char *str1,int sizeInByte, const char *str2){    char * s1;    s1 = str1;    while (*str2 != '\0' && sizeInByte){        *str1++ = *str2++;        sizeInByte--;    }    *str1++ = *str2++;    return s1;}static int _mMoveToCurentPtrByOffset(MEMFILE *stream){    struct MFileNode *node = NULL;    struct MFileNode *next = NULL;    size_t cnt = stream->offset / FILENODESIZE + 1;    next = stream->header;    while (cnt && NULL != next){        node = next;        next = node->next;        cnt--;    }    if (NULL == node){        stream->curnode = node;        stream->curptr = NULL;        stream->remain = 0;        return 0;    }    cnt = stream->offset % FILENODESIZE;    stream->remain = FILENODESIZE - cnt;    stream->curnode = node;    stream->curptr = node->lpBuffer + cnt;    return 0;}MEMFILE *mopen(const char * filename, const char * mode){    MEMFILE *mFile;    int len;    mFile = M_Malloc(sizeof(MEMFILE));    if (NULL == mFile){        return mFile;    }    len = _mstrlen(filename, MAX_FAILNAME);    mFile->filename = (char *)M_Malloc((len + 2)*sizeof(char));    if (NULL == mFile->filename){        M_Free(mFile);        return NULL;    }    _mstrcpy(mFile->filename,256, filename);    mFile->data_length = 0;    mFile->offset = 0;       /*offset from first element*/    mFile->remain = 0;      /*current node remain empty space*/    mFile->curptr = NULL;    mFile->header = NULL;    mFile->curnode = NULL;    mFile->endnode = NULL;    return mFile;}int mflush(MEMFILE *stream){    return 0;}int merror(MEMFILE *stream){    return 0;}int mclose(MEMFILE *stream){    struct MFileNode *node;    struct MFileNode *next;    mflush(stream);    next = stream->header;    while (NULL != next){        node = next;        next = node->next;        M_Free(node);    }    M_Free(stream->filename);    M_Free(stream);    return 0;}size_t mwrite(void* buf, size_t size, size_t count, MEMFILE *stream){    size_t         copy_len;    size_t          totall;    totall = size * count;    while (totall){        if (0 == stream->remain){   //if one block is full            if (NULL == stream->header){ //first write                struct MFileNode    *allocNode;                allocNode = (struct MFileNode *)M_Malloc(sizeof(struct MFileNode));                if (NULL == allocNode){                    break;                }                allocNode->next = NULL;                stream->header = allocNode;                stream->endnode = allocNode;                stream->curnode = allocNode;            }            else if (stream->curnode != stream->endnode){   //if There are blocks behind                stream->curnode = stream->curnode->next;            }            else{   //we need to alloc more block                struct MFileNode    *allocNode;                allocNode = (struct MFileNode *)M_Malloc(sizeof(struct MFileNode));                if (NULL == allocNode){                    break;                }                stream->curnode->next = allocNode;                allocNode->next = NULL;                stream->endnode = allocNode;                stream->curnode = allocNode;            }            stream->remain = FILENODESIZE;            stream->curptr = stream->curnode->lpBuffer;        }        copy_len = totall < stream->remain ? totall : stream->remain;        M_Memcpy(stream->curptr, buf, copy_len);        totall -= copy_len;        stream->remain -= copy_len;        stream->curptr += copy_len;        stream->offset += copy_len;        stream->data_length += copy_len;        buf = (void*)((char*)buf + copy_len);    }  //  if (totall == size * count)  //      return -1;    return (size * count - totall) / size;}size_t mread(void* buf, size_t size, size_t count, MEMFILE *stream){    size_t          dataless;    size_t          totall;    size_t         copy_len;    totall = size * count;    while (totall){        dataless = stream->data_length - stream->offset;        if (0 == dataless){            totall = size * count - totall;            return totall / size;        }        if (0 == stream->remain){            if (NULL == stream->header){                totall = size * count - totall;                return totall / size;            }            if (stream->curnode == stream->endnode){                totall = size * count - totall;                return totall / size;            }            stream->curnode = stream->curnode->next;            stream->remain = FILENODESIZE;            stream->curptr = stream->curnode->lpBuffer;        }        copy_len = stream->remain;        if (dataless < stream->remain){            copy_len = dataless;        }        copy_len = totall < copy_len ? totall : copy_len;        M_Memcpy(buf, stream->curptr, copy_len);        stream->offset += copy_len;        totall -= copy_len;        buf = (void*)((char*)buf + copy_len);        stream->curptr += copy_len;        stream->remain -= copy_len;    }    totall = size * count - totall;    return totall / size;}int mseek(MEMFILE *stream, long int offset, int origin){    switch (origin){        case MSEEK_CUR:stream->offset += offset; break;        case MSEEK_END:stream->offset = stream->data_length + offset; break;        case MSEEK_SET:stream->offset = offset; break;        default: return -1;    }    if (stream->offset > stream->data_length){        stream->offset = stream->data_length;    }    if (stream->offset < 0){        stream->offset = 0;    }    return _mMoveToCurentPtrByOffset(stream);}

更新于 2017/03/16

0 0