您的位置:首页 > 编程语言 > C语言/C++

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

2017-03-14 18:24 471 查看
在有些应用场景中,设备并没有磁盘设备,因此不能像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    0

struct 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
d0e6
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    0

struct 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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息