zoukankan      html  css  js  c++  java
  • 文件初始化简单高效的分块记录的实现

    每日一贴,明天的内容关键字为文件初始化

        在定长记载采用数据库读写并非最佳解决方案一文中,介绍了不管文件中记载数据为多少,只要按照文中介绍的方法存储,对于文件中恣意1条记载数据,在读缓冲内存恒定不变的情况下,最多只需要读文件1次,而且定位记载的算法也超等简略,只需做1次除法运算和1次求余运算。明天我在这里介绍一下它的C++实现方法。

        1.写记载

    #ifndef _WRITE_RECORD_H
    #define _WRITE_RECORD_H
    
    #include <qglobal.h>
    #include <qfile.h>
    
    #define  INDEX_BLK_RECORD_NUM          1000
    #define  RECORD_BLK_RECORD_NUM         1000
    #define  MAGIC                         "BETTARECORD"
    #define  MAGIC_LEN                     sizeof(MAGIC) - 1
    #pragma pack(1)
    typedef struct tagRecord {
        quint64 id;
        float cur;
        float vol;
        float tempe;
        float resistor;
    } TRecord;
    
    typedef struct tagFileHead {
        quint8 magic[MAGIC_LEN];
        quint32 version;
        quint32 indexBlkNum;
    } TFileHead;
    
    typedef struct tagBlkHead {
        quint64 nextBlkPos;
        quint32 recordNum;
    }TBlkHead;
    
    typedef struct tagIndexBlk {
        TBlkHead head;
        quint32 blkAddr[INDEX_BLK_RECORD_NUM];
    } TIndexBlk;
    
    typedef struct tagRecordBlk {
        TBlkHead blkHead;
        TRecord record[RECORD_BLK_RECORD_NUM];
    } TRecordBlk;
    
    #pragma pack()
    class CWriteRecord {
    
    public:
        CWriteRecord();
        ~CWriteRecord();
        bool openFile(const QString &fileName);
        void writeRecordHead(const TFileHead *pFileHead);
        void writeRecordBlk(const TRecord *pRecord);
        void flushBlk(bool bClose);
    
    private:
        void writeRecordBlkHead();
        void writeIndexBlk(quint64 blkPos);
        void writeIndexBlkNum();
        void writeIndexBlkHead();
        void init();
    
    private:
        QFile file;
    
        TBlkHead indexBlkHead;
        TBlkHead recordBlkHead;
    
        quint32 validIndexBlkRecordNum;
        quint32 validRecordBlkRecordNum;
    
        quint32 indexBlkNum;
        quint32 validIndexBlkNum;
    
        quint32 index;
        quint32 recordIndex;
    
        quint64 indexBlkPos;
        quint64 recordBlkPos;
    
        quint64 nextBlkPos;
    };
    #endif

        头文件提供了openFile,writeRecordHead,writeRecordBlk,flushBlk,四个公有接口,首先通过openFile打开一个文件,该文件可以是1个已存在的文件,也可以是1个不存在的文件,由fileName指定,openFile主动将文件初始化到就绪状态,打开当前,就能够使用writeRecordHead,writeRecordBlk,写记载了,flushBlk,是将文件flush到磁盘的操纵,接下来我们看看实现:

        每日一道理
    如果人类不好好保护我们这个赖以生存的地球,终有一天,风沙的肆虐与垃圾的堆积会吞没我们美丽的家园。我向全世界的人们呼吁:让我们从现在开始,从我做起,手挽手,肩并肩共同保护建设我们的家园吧!
    #include "writerecord.h"
    Queue CWriteRecord::queue;
    CWriteRecord::CWriteRecord()
    {
    
    }
    
    CWriteRecord::~CWriteRecord()
    {
    
    }
    
    bool CWriteRecord::openFile(const QString &fileName)
    {
        if (file.isOpen())
            file.close();
        file.setFileName(fileName);
        return file.open(QIODevice::Append | QIODevice::ReadWrite);
    }
    
    void CWriteRecord::writeRecordHead(const TRecordHead *pRecordHead)
    {
        file.seek(0);
        file.write((const char *)pRecordFileHead, sizeof(TRecordHead));
        init();   
    }
    
    
    void CWriteRecord::init()
    {
        recordBlkHead.recordNum = 0;
        indexBlkHead.recordNum = 0;
        validIndexBlkRecordNum = 0;
        validRecordBlkRecordNum = 0;
        
        indexBlkNum = 1;    
        validIndexBlkNum = 0;
        
        index = 0;
        recordIndex = 0;
        
        indexBlkPos = sizeof(TFileHead);
        recordBlkPos = indexBlkPos + sizeof(TIndexBlk);
        nextBlkPos = recordBlkPos + sizeof(TRecordBlk);
    }
    
    void CWriteRecord::writeRecordBlkHead()
    {
        if (validRecordBlkRecordNum != recordBlkHead.recordNum
            && recordBlkHead.recordNum != 0)
        {
            validRecordBlkRecordNum = recordBlkHead.recordNum;
            file.seek(recordBlkPos);
            file.write((const char *)&recordBlkHead, sizeof(recordBlkHead));
            writeIndexBlk(recordBlkPos);
        }
    }
    
    void CWriteRecord::writeRecordBlk(const TRecord *pRecord)
    {
        quint64 writePos = recordBlkPos + recordIndex * sizeof(TRecord) + sizeof(TBlkHead);
        file.seek(writePos);
        file.write((const char *)pRecord, sizeof(TRecord));
    
        recordIndex++;
        recordBlkHead.recordNum = recordIndex;
        if (recordIndex == RECORD_BLK_RECORD_NUM)
        {
            /*写当前块*/
            recordBlkHead.nextBlkPos = nextBlkPos;
            writeRecordBlkHead();
    
            /*初始化下一块*/
            recordBlkHead.recordNum = 0;
            recordBlkPos = nextBlkPos;
            recordIndex = 0;
            recordBlkNum++;
    
            nextBlkPos = nextBlkPos + sizeof(TRecordBlk);
        }
    }
    
    
    void CWriteRecord::writeIndexBlkHead()
    {
        if (validIndexBlkRecordNum != indexBlkHead.recordNum
            && indexBlkHead.recordNum != 0)
        {
            validIndexBlkRecordNum = indexBlkHead.recordNum;
            file.seek(indexBlkPos);
            file.write((const char *)&indexBlkHead, sizeof(indexBlkHead));
            writeIndexBlkNum();
        }
    }
    
    void CWriteRecord::writeIndexBlkNum()
    {
        if (validIndexBlkNum != indexBlkNum)
        {
            validIndexBlkNum = indexBlkNum;
    
            quint32 writePos = (quint32)&((TFileHead *)0)->indexBlkNum;
            file.seek(writePos);
            file.write((const char *)&indexBlkNum, sizeof(indexBlkNum));
        }
    }
    
    void CWriteRecord::writeIndexBlk(quint64 blkPos)
    {
        quint64 writePos = indexBlkPos + index * sizeof(TIndex) + sizeof(TBlkHead);
        file.seek(writePos);
        file.write((const char *)&blkPos, sizeof(blkPos));
    
        index++;
        indexBlkHead.recordNum = index;
        quint32 blkRecordNum = INDEX_BLK_RECORD_NUM;
        if (index == blkRecordNum)
        {
            /*写当前块*/
            indexBlkHead.nextBlkPos = nextBlkPos;
            writeIndexBlkHead();
    
            /*初始化下一块*/
            indexBlkHead.recordNum = 0;
            indexBlkPos = nextBlkPos;
            index = 0;
            indexBlkNum++;
    
            nextBlkPos = nextBlkPos + sizeof(TIndexBlk);
        }
    }
    
    
    void CWriteRecord::flushBlk(bool bClose)
    {
        if (file.isOpen())
        {
            writeRecordBlkHead();
            if (bClose)
                file.close();
            else
                file.flush();
        }
    }

        
    2.读记载

    #ifndef _READ_RECORD_H
    #define _READ_RECORD_H
    
    #include <qglobal.h>
    #include <qfile.h>
    class CReadRecord {
    
    public:
        static CReadRecord *getInstance();
        const TRecordBlk &readRecordBlk(quint64 blkPos);
        bool read(const QString &fileName);
        const QVector <quint64> *getRecordBlkPosList();
    
    
    private:
        CReadRecord();
        void readRecordHead();
        void initBlkPosList();
    
    private:
        QFile file;
        TRecordBlk recordBlk;
        TIndexBlk indexBlk;
    
        TRecordHead recordHead;
        QVector <quint64> recordBlkPosList;
        static CReadRecord mSelf;
    };
    #endif
    #include "readrecord.h"
    CReadRecord CReadRecord::mSelf;
    CReadRecord *CReadRecord::getInstance()
    {
        return &mSelf;
    }
    
    CReadRecord::CReadRecord()
    {
    
    }
    
    bool CReadRecord::read(const QString &fileName)
    {
        if (file.isOpen())
            file.close();
        file.setFileName(fileName);
        if (!file.open(QIODevice::ReadOnly))
            return false;
        readRecordHead();
        if (memcmp(recordHead.magic,
                   FILE_MAGIC,
                   FILE_MAGIC_LEN) == 0)
        {
            initBlkPosList();
            return true;
        }
        return false;
    }
    
    const QVector <quint64> *CReadRecord::getRecordBlkPosList()
    {
        return &recordBlkPosList;
    }
    
    
    void CReadRecord::readRecordHead()
    {
        file.seek(0);
        file.read((char *)&recordHead, sizeof(TRecordHead));
    }
    
    
    const TRecordBlk &CReadRecord::readRecordBlk(quint64 blkPos)
    {
        readFile(blkPos, (quint8 *)&recordBlk, sizeof(recordBlk));
        return recordBlk;
    }
    
    void CReadRecord::initBlkPosList()
    {
        recordBlkPosList.clear();
        int cnt = recordHead.indexBlkNum;
        quint64 indexBlkPos = sizeof(TRecordHead);
        for (int i = 0; i < cnt; i++)
        {
            readFile(indexBlkPos, (quint8 *)&indexBlk, sizeof(indexBlk));
            int cnt1 = indexBlk.blkHead.recordNum;
            for (int j = 0; j < cnt1; j++)
            {
                recordBlkPosList.append(indexBlk.index[j]);
            }
            indexBlkPos = indexBlk.blkHead.nextBlkPos;
        }
    }

        
     

    文章结束给大家分享下程序员的一些笑话语录: 3G普不普及现在已经不是看终端了,而是看应用,有好的,便宜实用的应用,花1000多买个能用的智能手机应该不是什么难事。反过来说,你200元拿一个智能手机,没有好的应用,看个电影要几十元,也是没人用3G。

  • 相关阅读:
    Leetcode424. 替换后的最长重复字符
    Leetcode82. 删除排序链表中的重复元素 II
    python 无序模块,hashlib模块
    python 内置方法
    python 面向对象的三大特性
    python 面向对象
    python 递归函数和二分查找
    python 装饰器
    python 函数名,闭包
    python 函数进阶
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3093468.html
Copyright © 2011-2022 走看看