文件初始化简单高效的分块记录的实现
每日一贴,明天的内容关键字为文件初始化
在定长记载采用数据库读写并非最佳解决方案一文中,介绍了不管文件中记载数据为多少,只要按照文中介绍的方法存储,对于文件中恣意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。