文件初始化简单高效的分块记录的实现

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

    在定长记载采用数据库读写并非最佳解决方案一文中,介绍了不管文件中记载数据为多少,只要按照文中介绍的方法存储,对于文件中恣意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。

posted @ 2013-05-22 20:01  坚固66  阅读(294)  评论(0编辑  收藏  举报