1. 程式人生 > >對映檔案到記憶體,像操作記憶體一樣方便讀寫檔案——MemFile

對映檔案到記憶體,像操作記憶體一樣方便讀寫檔案——MemFile

編碼中操作檔案是常有的事,本文封裝了一種不一樣的讀寫檔案方式,通過對映檔案可以想操作記憶體一樣方便的讀寫檔案。

方法解釋:

Attach:關聯已存在的檔案並對映到記憶體,不存在返回NULL;

Detach:取消關聯機器對映;

Alloc:建立一個新的檔案並對映到記憶體;

Calloc:如果已經存在則清空;

Aalloc:匿名對映;

Realloc:已經存在直接對映,不存在則建立一個;

Release:釋放,功能同Detach;

Exist:判斷是否存在;

Makedir:建立目錄,可以多級目錄

Delete:刪除檔案;

Length:求檔案大小;

有原始碼有真相,下面是原始碼:

class MemFile
{
public:
    static void* Attach(const char *name)
    {
        size_t filelen = Length(name);
        if(-1 == filelen) return NULL;

        int fd = open(name, O_RDWR);
        if(-1 == fd) return NULL;

        void *addr = mmap(NULL, filelen, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0);
        close(fd);
        
        if(MAP_FAILED == addr)return NULL;
        
        return addr;
    }
    
    static void Detach(void *addr, size_t length)
    {
        if(addr != NULL && length != -1) munmap(addr, length);
    }
    
    static void* Alloc(const char *name, size_t length)
    {
        int fd = open(name, O_RDWR|O_CREAT|O_EXCL, 0644);
        if(-1 == fd) return NULL;

        if(ftruncate(fd, length) != 0) {close(fd); return NULL;}
        
        void *addr = mmap(NULL, length, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0);
        close(fd);
        
        if(MAP_FAILED == addr)return NULL;
        
        return addr;
    }

    static void* Calloc(const char *name, size_t length)
    {
        int fd = open(name, O_RDWR|O_CREAT|O_TRUNC, 0644);
        if(-1 == fd) return NULL;

        if(ftruncate(fd, length) != 0) {close(fd); return NULL;}
        
        void *addr = mmap(NULL, length, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0);
        close(fd);
        
        if(MAP_FAILED == addr)return NULL;
        
        return addr;
    }

    static void* Aalloc(size_t length)
    {
        void *addr = mmap(NULL, length, PROT_WRITE|PROT_READ, MAP_ANONYMOUS, -1, 0);
        if(MAP_FAILED == addr)return NULL;
        
        return addr;
    }
    
    static void* Realloc(const char *name, size_t length)
    {
        if(Length(name) == length) return Attach(name);
        else if(Length(name) == -1) return Alloc(name, length);
        else return NULL;
    }

    static void Release(void *addr, size_t length)
    {
        if(addr != NULL && length != -1) munmap(addr, length);
    }
    
    static bool Exist(const char *name)
    {
        if(access(name, F_OK) == 0) return true;

        return false;
    }
    
    static bool Makedir(const char *name)
    {
        size_t len = strlen(name);
        char dir[256] = {0};
        if(len >= sizeof(dir)) return false;
        for(size_t i = 0; i < len; ++i)
        {
            if(name[i] == '/')
            {
                strncpy(dir, name, i+1);

                if(Exist(dir)) continue;
                if(mkdir(dir, 0755) == -1) return false;
            }
        }

        return true;
    }
    
    static void Delete(const char *name)
    {
        remove(name);
    }
    
    static size_t Length(const char *name)
    {
        struct stat statbuff;
        if(stat(name, &statbuff) < 0) return -1;
        
        return statbuff.st_size;
    }
};