📄 dbsfile.cpp
字号:
#include "DbsFile.h"
#include <dos.h>
#include <dir.h>
//该数据库保存记录的批次数为245批抄表读数,3批结算日数据。
//每167K的内存最多可以保存64块表,也即数据库大小必须为167K的倍数
int CDbsFile::CreateNewDbs()
{
//计算数据库文件大小
struct dfree free;
unsigned long FreeSpaceKB;
unsigned long NewFileSize;
getdfree(getdisk()+1, &free);//获得当前磁盘的基本信息。
if(free.df_sclus == 0xFFFF) return 1;//产生失败
FreeSpaceKB=(unsigned long) free.df_avail*(unsigned long) free.df_bsec* (unsigned long) free.df_sclus/1024L;
FreeSpaceKB-=384;//剩余空间少384K
if(FreeSpaceKB>0x4000L) FreeSpaceKB=0x4000L;//最大文件空间为16M=0x4000K
if(1) FreeSpaceKB=1024;
//数据库文件大小
NewFileSize=FreeSpaceKB/167*167;//文件大小,单位多少K
memset(m_HubMsgData,0,192);
//库标志 8 +0 缺省为Device
memcpy(m_HubMsgData,"Device",6);
//库文件长度 4 +8 (单位字节)
ULongInt(m_HubMsgData+8)=NewFileSize*1024L;
//系统区大小 4 +12
ULongInt(m_HubMsgData+12)=(NewFileSize/167*64*192);
//最大存储表数 2 +16
UShortInt(m_HubMsgData+16)=(unsigned short int)(NewFileSize/167*64)-1;
//集中器编号 4 +24 缺省:1234567890
ULongInt(m_HubMsgData+24)=1234567890L;
//一般用户密码 4 +28 缺省:1234
ULongInt(m_HubMsgData+28)=GetPWDLongIntValue("1234",4);
//超级用户密码 4 +32 缺省:12345678
ULongInt(m_HubMsgData+32)=GetPWDLongIntValue("12345678",8);
//CRC校验码 4 +188 前188字节
ULongInt(m_HubMsgData+188)=GetFileDataCrc(m_HubMsgData,188);
//创建文件,文件大小为:NewFileSize
FILE *fp=fopen(DbsFileName,"wb");
char buf[1024]={0};
cprintf("\r\nCreateNewDbs(%ldK)...",NewFileSize);
for(;NewFileSize>0;NewFileSize--)
{
fwrite(buf,1024,1,fp);
if(NewFileSize%2048==0) cprintf(" %2lu",NewFileSize/2048);
}
fseek(fp,0,SEEK_SET);
fwrite(m_HubMsgData,192,1,fp);
fclose(fp);
cprintf("...OK");
return 0;
}
//1=错误 0=OK
int CDbsFile::CheckDBSFileHead(FILE *fp)
{
long FileLen;
char buf[192]={1};
fseek(fp,0,SEEK_SET);
if(fread(buf,192,1,fp)!=1) return 0;
if(ULongInt(buf+188)!=GetFileDataCrc(buf,188)) return 1;
fseek(fp,0,SEEK_END);
FileLen=ftell(fp);
if(memcmp(buf,"Device",6)
||(LongInt(buf+8)!=FileLen)
||(LongInt(buf+12)!=FileLen*12/167)
||(UShortInt(buf+16)!=FileLen/2672-1)) return 1;
return 0;
}
void CDbsFile::ReadDBS()
{
m_DBSFile=fopen(DbsFileName,"rb+");
if((!m_DBSFile)||CheckDBSFileHead(m_DBSFile))
{
if(m_DBSFile) fclose(m_DBSFile);
CreateNewDbs();
m_DBSFile=fopen(DbsFileName,"rb+");
if(!m_DBSFile) return ;
}
fseek(m_DBSFile,0,SEEK_SET);
fread(m_HubMsgData,192,1,m_DBSFile);
m_DataOffset=ULongInt(m_HubMsgData+12);
m_CurMeterCount=0;
m_MaxMeterCount=UShortInt(m_HubMsgData+16);
if(!m_Dbs.SetSize(m_MaxMeterCount+1))
{
m_ErrorCode=1;
return;
}
struct CMemMeter NewMemMeter={0},TempMeter;
long k,i;
char buf[192];
m_Dbs[0]=NewMemMeter;
for(k=1;k<=m_MaxMeterCount;k++)
{
fread(buf,192,1,m_DBSFile);
memset(&NewMemMeter,0,sizeof(struct CMemMeter));
if(ULongInt(buf+188)==GetFileDataCrc(buf,188) && UShortInt(buf)!=0)
{
m_CurMeterCount++;
NewMemMeter.MeterNo=UShortInt(buf);
//NewMemMeter.TransformerId; //区号:台变标识
//NewMemMeter.uArea; //片号:片区号,该表所在片区号
//NewMemMeter.SpecialMeter
//NewMemMeter.uRelay[5]; //中继信息:最高位=0无效,1=有效,低四位为中继水平。
}
else NewMemMeter.MeterNo=0xFFFF;
NewMemMeter.uFileIndex=(unsigned short)k;//0为中继中继表号 ???k-1"???
//按表号从小到大排序,插入排序到数据库中
i=k-1;
TempMeter=m_Dbs[i];
while(TempMeter.MeterNo>NewMemMeter.MeterNo)
{
m_Dbs[i+1]=TempMeter;
i--;
TempMeter=m_Dbs[i];
}
m_Dbs[i+1]=NewMemMeter;
}
}
unsigned short int CDbsFile::FindMeterMemoryIndex(unsigned short MeterNo)
{
if((MeterNo==0)||(MeterNo==0xFFFF)) return 0;
unsigned short int low=1,high=m_CurMeterCount,mid;
unsigned long int MidMeterNo;
while(low<=high)
{
mid=(low+high)/2;
MidMeterNo=m_Dbs[mid].MeterNo;
if(MeterNo>MidMeterNo) low=mid+1;
else if(MeterNo<MidMeterNo) high=mid-1;
else return mid;
}
return 0;
}
////////////////////////////////////////////////////////////////////////////
// 数据库操作
////////////////////////////////////////////////////////////////////////////
//清除所有的表。
void CDbsFile::EmptyAllMeter()
{
struct CMemMeter *ptrMemMeter;
long k;
char buf[1024]={0};
PreEmptyAllMeter(ULongInt(m_HubMsgData+8));
//清楚数据库数据
fseek(m_DBSFile,192,SEEK_SET);
fwrite(buf,1024-192,1,m_DBSFile);
for(k=ULongInt(m_HubMsgData+8)/1024-1;k>0;k--) fwrite(buf,1024,1,m_DBSFile);
flush(m_DBSFile);
//清楚内存数据
for(k=1;k<=m_MaxMeterCount;k++)
{
ptrMemMeter=m_Dbs.GetAddr(k);
ptrMemMeter->MeterNo=0xFFFF;
ptrMemMeter->uFileIndex=(unsigned short)k;
}
m_CurMeterCount=0;
//清除swp文件的数据
ClearSwpFile();
}
//写系统区的第Position个192字节
void CDbsFile::WriteBasicMeterDataToFile(unsigned char data[], int Position)
{
if(!m_DBSFile)
{
cprintf("\r\nSYSTEM ERROR:m_DBSFile is NULL");
return;
}
ULongInt(data+188)=GetFileDataCrc(data,188);
if(Position==0) memcpy(m_HubMsgData,data,192);
//先写swp文件
PreWriteDataToSwpFile(data,Position);
//再写到数据库中
fseek(m_DBSFile,Position*192L,SEEK_SET);
fwrite(data,192,1,m_DBSFile);
flush(m_DBSFile);
//清除swp文件的数据
ClearSwpFile();
}
void CDbsFile::AppendORModifyMeter(const char *Data)
{
unsigned short int NewMeterNO=UShortInt(Data);
struct CMemMeter *ptrMeterMem=FindMeterMemoryAddr(NewMeterNO);
if(ptrMeterMem)
{
//修改表资料
cprintf(" %u(*)",NewMeterNO);
}
else
{
//增加新表
cprintf(" %u(+)",NewMeterNO);
}
}
void CDbsFile::DeleteMeter(const unsigned short delMeterNo)
{
unsigned short DelIndex=FindMeterMemoryIndex(delMeterNo);
cprintf(" %u(-)",delMeterNo);
if(DelIndex)
{
long k;
unsigned char buf[192]={0};
unsigned short DelMeterFileIndex;
struct CMemMeter TempMeter;
DelMeterFileIndex=m_Dbs[DelIndex].uFileIndex;
//先写swp文件
PreWriteDataToSwpFile(buf,DelMeterFileIndex);
//清除文件内容
fseek(m_DBSFile,DelMeterFileIndex*192L,SEEK_SET);
fwrite(buf,192,1,m_DBSFile);
flush(m_DBSFile);
//清除swp文件的数据
ClearSwpFile();
//删除内存表号。移动到最后
for(k=DelIndex;k<m_CurMeterCount;k++)
{
TempMeter=m_Dbs[k+1];
m_Dbs[k]=TempMeter;
}
memset(&TempMeter,0,sizeof(struct CMemMeter));
TempMeter.MeterNo=0xFFFF;
TempMeter.uFileIndex=DelMeterFileIndex;
m_Dbs[m_CurMeterCount]=TempMeter;
m_CurMeterCount--;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -