大多數(shù)的應(yīng)用程序都有需要配置的參數(shù),配置參數(shù)的保存有多種方法,比如采用數(shù)據(jù)庫保存、二進制文件保存、格式化的文本文件保存,各有優(yōu)缺點,對于一般小的安全性要求不高應(yīng)用程序,推薦采用格式化文本文件保存方式,這樣可以節(jié)約編輯修改的界面編程,使用記事本程序編輯即可。
早期的windows就是采用的INI格式文本文件?,F(xiàn)在很多應(yīng)用程序包括大型的軟件也還在采用格式化文本文件保存配置參數(shù),比如Bentely MicroStation GIS平臺GEOGRAPHICS8.0。
本文給出的就是利用VC來讀取和分析配置文本文件,這是筆者這消防監(jiān)控系統(tǒng)遠程終端軟件使用的方法。同時給出一個C++類來封裝配置文本文件的讀取分析。
下面是我采用的配置文件的例子,包含單個參數(shù)定義,表格參數(shù)定義,注釋:
// 協(xié)議名稱: TL
// 工程: SQ
// 配置人: JY
#DEFINE_BEGIN //以下為常量定義
//通信參數(shù)
@COM_PORT \\\\.\\COM1 //COM口
@COM_BAUDRATE 1200 //波特率
@COM_BITSIZE 8 //數(shù)據(jù)位 number of bits/byte, 4-8
@COM_SBIT 0 // 0,1,2 對應(yīng) 1, 1.5, 2
@COM_PARITY 0 //0-4對應(yīng)no,odd,even,mark,space
@STATIONNO 0 //終端號
@TCPIP_SERVERIP 192.168.0.10 //服務(wù)器IP地址
@TCPIP_PORTNO 3024 //端口
#DEFINE_END
#TABLE_BEGIN //表格
//編號 識別字符串
//例子如下
0 Ion Detector, ALU1, L1S43 //測量臺2#離子煙感探測器 報警
1 Thermal Det, ALU1, L1S39 //值班室溫感探測器報警
#TABLE_END
語法解釋:
// 單行注釋
#DEFINE_BEGIN 單個參數(shù)定義的開始標(biāo)記
#DEFINE_END 單個參數(shù)定義的結(jié)束標(biāo)記
#TABLE_BEGIN 表格參數(shù)開始標(biāo)記
#TABLE_END 表格參數(shù)結(jié)束標(biāo)記
單個參數(shù)的配置:
每個參數(shù)一行:以空格、TAB制表符作為分隔,注釋可選,每行結(jié)束后有Enter鍵換行。
表格參數(shù)配置:第一列為數(shù)字編號,作為ID用,第一列和第二列之間采用空格、TAB制表符作為分隔,其他列之間采用’,’逗號、空格、TAB制表符分隔,因此從第二列起,字符串中間夾的空格是有效字符。比如上面例子中的第一行解釋如下:
\"0\",\"Ion Detector\",\"ALU1\",\"L1S43\"
同樣,表格參數(shù)也是每行有Enter鍵換行。
下面給出一個C++類來完成這個格式的文本配置讀取和分析。
規(guī)模:
文本文件的大?。?48kbytes
單個參數(shù)定義個數(shù):不限
表格參數(shù)定義: 100行 X 4列
這些規(guī)模大小可以修改下面的宏定義來滿足你的需要
#define TABLE_MAXROW 100
#define TABLE_MAXCOL 5 //含索引ID列
typedef struct{
int nID;
char s[TABLE_MAXCOL-1][64];
}TAG_TABLEREC,*LPTABLEREC;
class CDataTxt
{
public:
CDataTxt();
~CDataTxt();
CString m_szPath;//配置文件全路經(jīng)名
BOOL Read();//讀入文件
BOOL GetDefine(LPCTSTR lpszName,CString &szVal);//獲取定義
//{{TABLE
TAG_TABLEREC m_Table[TABLE_MAXROW];
int m_nRows;
//}}
private:
char m_cbuf[1024*48];
int m_nBufSize;//=1024*48;
int m_nDataSize;
CString m_szDefine;//定義段
int m_nDefineLen;
CString m_szTable;//表格段
int m_nTableLen;
void DelNote();//去掉注釋
void FormatTable(void);//規(guī)格化表格
};
CDataTxt::CDataTxt()
{
int i;
m_szPath=\"SQTL.txt\";
m_nBufSize=1024*48;
m_nDataSize=0;
m_nDefineLen=0;
m_nTableLen=0;
for(i=0;i m_cbuf=0;
ZeroMemory(&m_Table,sizeof(m_Table));
m_nRows=0;
}
CDataTxt::~CDataTxt()
{
}
BOOL CDataTxt::Read()
{
CFile fl;
if(!fl.Open(m_szPath,CFile::modeRead|CFile::typeBinary))
return FALSE;
DWORD dwl=fl.GetLength();
if(dwl > (DWORD)m_nBufSize)
dwl=(DWORD)m_nBufSize;
m_nDataSize=(int)(fl.Read(m_cbuf,dwl));
fl.Close();
DelNote();//去掉注釋
return TRUE;
}
void CDataTxt::DelNote()//去掉注釋,分成定義段和表格段
{
CString szt=\"\";
char cc,ccp=0;
int i;
for(i=0;i {
cc=m_cbuf;
if(cc != ’/’){ szt+=cc;ccp=cc; }
else//cc==’/’
{
if(i {
if(m_cbuf[i+1]==’/’)//注釋開始
{
while((i if(m_cbuf==0x0d) i--;
ccp=0;
}
else{szt+=cc; ccp=cc; }
}
}
}
m_nDataSize=szt.GetLength();
sprintf(m_cbuf,\"%s\",szt);
int ns=szt.Find(\"#DEFINE_BEGIN\",0);
int ne=szt.Find(\"#DEFINE_END\",0);
if((ns==-1)||(ne==-1)) return;
ns+=13;
m_szDefine=\"\";
for(i=ns;i m_nDefineLen=m_szDefine.GetLength();
ns=szt.Find(\"#TABLE_BEGIN\",0);
ne=szt.Find(\"#TABLE_END\",0);
ns+=12;
if((ns==-1)||(ne==-1)) return;
m_szTable=\"\";
for(i=ns;i m_nTableLen=m_szTable.GetLength();
FormatTable();//規(guī)格化表格
}BOOL CDataTxt::GetDefine(LPCTSTR lpszName,CString &szVal)//獲取定義
{
CString szName=lpszName;
if(szName.IsEmpty()) return FALSE;
int nLen=szName.GetLength();
int ns=m_szDefine.Find(lpszName,0);
if(ns==-1) return FALSE;
szVal=\"\";
int i=ns+nLen;
BOOL bStartCopy=FALSE;
char cc;
while(i {
cc=m_szDefine;
if((cc!=0x0D)&&(cc!=0x0A)&&(cc!=’\\t’)&&(cc!=0x20))
{
if(bStartCopy==FALSE) bStartCopy=TRUE;
szVal+=m_szDefine;
}
else{if(bStartCopy) break;} i++;
}
return TRUE; }
void CDataTxt::FormatTable()//規(guī)格化表格
{
int i=0;
char cc;
int nRow=0;
CString szLine=\"\",szID=\"\",szVal=\"\",szCol=\"\";
int nCol=0;
while(i {
cc=m_szTable;
if((cc==0x0A)||(cc==’\\t’)) cc=0x20;
if(cc==0X0D)//處理一行
{
szLine.TrimLeft(); szLine.TrimRight();
if(!szLine.IsEmpty())
{
int nl=szLine.GetLength();
int j;
char c;
szID=\"\";
for(j=0;j {
c=szLine[j];
if(c==0x20)
break;
szID+=c;
}
m_Table[nRow].nID=atoi(szID);
BOOL bStart;
bStart=FALSE;
szVal=\"\";
while(j {
c=szLine[j];
if((bStart==FALSE)&&(c==0x20)) j++;
else{bStart=TRUE;szVal+=c;j++;}
}
szVal.TrimLeft();szVal.TrimRight();
nCol=0; nl=szVal.GetLength();
j=0;szCol=\"\";
while(j {
c=szVal[j];
if(c==’,’)
{
if(szCol.IsEmpty()) break;
else
{
if(nCol < TABLE_MAXCOL-1)
{
if(szCol.GetLength() <64)
sprintf(&(m_Table[nRow].s[nCol][0]),\"%s\",szCol);
nCol++; TRACE(\"szCol=%s\\n\",szCol);
}
}
szCol=\"\";
}
else szCol+=c;
j++;
}
if(!szCol.IsEmpty())
{
if(nCol < TABLE_MAXCOL-1)
{
if(szCol.GetLength() <64)
sprintf(m_Table[nRow].s[nCol],\"%s\",szCol);
nCol++; TRACE(\"szCol=%s\\n\",szCol);
}
}
if(nCol>0)
nRow++;
if(m_nRows >=TABLE_MAXROW)
{
m_nRows=nRow;
return;
}
szLine=\"\";
}
}
else szLine+=cc;
i++;
}
m_nRows=nRow;
}
void test()
{
CDataTxt dt;
dt.m_szPath=\"c:\\\\sqtl.txt\";
dt.Read();
CString szVal,szMsg;
if(dt.GetDefine(\"@COM_PORT\",szVal)){TRACE(\"@COM_PORT=%s\\n\",szVal);}
if(dt.GetDefine(\"@COM_BAUDRATE\",szVal)){TRACE(\"@COM_BAUDRATE=%s\\n\",szVal);}
int i;
for(i=0;i {
TRACE(\"Row=%d,ID=%d,s[0]=%s,sz[1]=%s,s[2]=%s,s[3]=%s\\n\",
i,
dt.m_Table.nID,
&(dt.m_Table.s[0][0]),
&(dt.m_Table.s[1][0]),
&(dt.m_Table.s[2][0]),
&(dt.m_Table.s[3][0]));
}
}
文件讀?。?BR> void CShotdetect::WritetoText(int p1, LONGLONG p2)
{
CString str;
str = \"c:\\\\文本文件.txt\";
CFile file;
file.Open(str,CFile::modeCreate|CFile::modeReadWrite|CFile::modeNoTruncate);
char ch_str1[30];
char ch_str2[20];
_itoa(p1,ch_str1,10);
strcat(ch_str1,\",\");
_itoa(p2,ch_str2,10);
strcat(ch_str1,ch_str2);
strcat(ch_str1,\"\\n\");
int length = 0;
for(int i = 0;i<30;i++)
{
if(ch_str1!=’\\0’)
length++;
else
break;
}
file.SeekToEnd();
file.Write(ch_str1,length);
file.Close();
早期的windows就是采用的INI格式文本文件?,F(xiàn)在很多應(yīng)用程序包括大型的軟件也還在采用格式化文本文件保存配置參數(shù),比如Bentely MicroStation GIS平臺GEOGRAPHICS8.0。
本文給出的就是利用VC來讀取和分析配置文本文件,這是筆者這消防監(jiān)控系統(tǒng)遠程終端軟件使用的方法。同時給出一個C++類來封裝配置文本文件的讀取分析。
下面是我采用的配置文件的例子,包含單個參數(shù)定義,表格參數(shù)定義,注釋:
// 協(xié)議名稱: TL
// 工程: SQ
// 配置人: JY
#DEFINE_BEGIN //以下為常量定義
//通信參數(shù)
@COM_PORT \\\\.\\COM1 //COM口
@COM_BAUDRATE 1200 //波特率
@COM_BITSIZE 8 //數(shù)據(jù)位 number of bits/byte, 4-8
@COM_SBIT 0 // 0,1,2 對應(yīng) 1, 1.5, 2
@COM_PARITY 0 //0-4對應(yīng)no,odd,even,mark,space
@STATIONNO 0 //終端號
@TCPIP_SERVERIP 192.168.0.10 //服務(wù)器IP地址
@TCPIP_PORTNO 3024 //端口
#DEFINE_END
#TABLE_BEGIN //表格
//編號 識別字符串
//例子如下
0 Ion Detector, ALU1, L1S43 //測量臺2#離子煙感探測器 報警
1 Thermal Det, ALU1, L1S39 //值班室溫感探測器報警
#TABLE_END
語法解釋:
// 單行注釋
#DEFINE_BEGIN 單個參數(shù)定義的開始標(biāo)記
#DEFINE_END 單個參數(shù)定義的結(jié)束標(biāo)記
#TABLE_BEGIN 表格參數(shù)開始標(biāo)記
#TABLE_END 表格參數(shù)結(jié)束標(biāo)記
單個參數(shù)的配置:
每個參數(shù)一行:以空格、TAB制表符作為分隔,注釋可選,每行結(jié)束后有Enter鍵換行。
表格參數(shù)配置:第一列為數(shù)字編號,作為ID用,第一列和第二列之間采用空格、TAB制表符作為分隔,其他列之間采用’,’逗號、空格、TAB制表符分隔,因此從第二列起,字符串中間夾的空格是有效字符。比如上面例子中的第一行解釋如下:
\"0\",\"Ion Detector\",\"ALU1\",\"L1S43\"
同樣,表格參數(shù)也是每行有Enter鍵換行。
下面給出一個C++類來完成這個格式的文本配置讀取和分析。
規(guī)模:
文本文件的大?。?48kbytes
單個參數(shù)定義個數(shù):不限
表格參數(shù)定義: 100行 X 4列
這些規(guī)模大小可以修改下面的宏定義來滿足你的需要
#define TABLE_MAXROW 100
#define TABLE_MAXCOL 5 //含索引ID列
typedef struct{
int nID;
char s[TABLE_MAXCOL-1][64];
}TAG_TABLEREC,*LPTABLEREC;
class CDataTxt
{
public:
CDataTxt();
~CDataTxt();
CString m_szPath;//配置文件全路經(jīng)名
BOOL Read();//讀入文件
BOOL GetDefine(LPCTSTR lpszName,CString &szVal);//獲取定義
//{{TABLE
TAG_TABLEREC m_Table[TABLE_MAXROW];
int m_nRows;
//}}
private:
char m_cbuf[1024*48];
int m_nBufSize;//=1024*48;
int m_nDataSize;
CString m_szDefine;//定義段
int m_nDefineLen;
CString m_szTable;//表格段
int m_nTableLen;
void DelNote();//去掉注釋
void FormatTable(void);//規(guī)格化表格
};
CDataTxt::CDataTxt()
{
int i;
m_szPath=\"SQTL.txt\";
m_nBufSize=1024*48;
m_nDataSize=0;
m_nDefineLen=0;
m_nTableLen=0;
for(i=0;i
ZeroMemory(&m_Table,sizeof(m_Table));
m_nRows=0;
}
CDataTxt::~CDataTxt()
{
}
BOOL CDataTxt::Read()
{
CFile fl;
if(!fl.Open(m_szPath,CFile::modeRead|CFile::typeBinary))
return FALSE;
DWORD dwl=fl.GetLength();
if(dwl > (DWORD)m_nBufSize)
dwl=(DWORD)m_nBufSize;
m_nDataSize=(int)(fl.Read(m_cbuf,dwl));
fl.Close();
DelNote();//去掉注釋
return TRUE;
}
void CDataTxt::DelNote()//去掉注釋,分成定義段和表格段
{
CString szt=\"\";
char cc,ccp=0;
int i;
for(i=0;i
cc=m_cbuf;
if(cc != ’/’){ szt+=cc;ccp=cc; }
else//cc==’/’
{
if(i
if(m_cbuf[i+1]==’/’)//注釋開始
{
while((i
ccp=0;
}
else{szt+=cc; ccp=cc; }
}
}
}
m_nDataSize=szt.GetLength();
sprintf(m_cbuf,\"%s\",szt);
int ns=szt.Find(\"#DEFINE_BEGIN\",0);
int ne=szt.Find(\"#DEFINE_END\",0);
if((ns==-1)||(ne==-1)) return;
ns+=13;
m_szDefine=\"\";
for(i=ns;i
ns=szt.Find(\"#TABLE_BEGIN\",0);
ne=szt.Find(\"#TABLE_END\",0);
ns+=12;
if((ns==-1)||(ne==-1)) return;
m_szTable=\"\";
for(i=ns;i
FormatTable();//規(guī)格化表格
}BOOL CDataTxt::GetDefine(LPCTSTR lpszName,CString &szVal)//獲取定義
{
CString szName=lpszName;
if(szName.IsEmpty()) return FALSE;
int nLen=szName.GetLength();
int ns=m_szDefine.Find(lpszName,0);
if(ns==-1) return FALSE;
szVal=\"\";
int i=ns+nLen;
BOOL bStartCopy=FALSE;
char cc;
while(i
cc=m_szDefine;
if((cc!=0x0D)&&(cc!=0x0A)&&(cc!=’\\t’)&&(cc!=0x20))
{
if(bStartCopy==FALSE) bStartCopy=TRUE;
szVal+=m_szDefine;
}
else{if(bStartCopy) break;} i++;
}
return TRUE; }
void CDataTxt::FormatTable()//規(guī)格化表格
{
int i=0;
char cc;
int nRow=0;
CString szLine=\"\",szID=\"\",szVal=\"\",szCol=\"\";
int nCol=0;
while(i
cc=m_szTable;
if((cc==0x0A)||(cc==’\\t’)) cc=0x20;
if(cc==0X0D)//處理一行
{
szLine.TrimLeft(); szLine.TrimRight();
if(!szLine.IsEmpty())
{
int nl=szLine.GetLength();
int j;
char c;
szID=\"\";
for(j=0;j
c=szLine[j];
if(c==0x20)
break;
szID+=c;
}
m_Table[nRow].nID=atoi(szID);
BOOL bStart;
bStart=FALSE;
szVal=\"\";
while(j
c=szLine[j];
if((bStart==FALSE)&&(c==0x20)) j++;
else{bStart=TRUE;szVal+=c;j++;}
}
szVal.TrimLeft();szVal.TrimRight();
nCol=0; nl=szVal.GetLength();
j=0;szCol=\"\";
while(j
c=szVal[j];
if(c==’,’)
{
if(szCol.IsEmpty()) break;
else
{
if(nCol < TABLE_MAXCOL-1)
{
if(szCol.GetLength() <64)
sprintf(&(m_Table[nRow].s[nCol][0]),\"%s\",szCol);
nCol++; TRACE(\"szCol=%s\\n\",szCol);
}
}
szCol=\"\";
}
else szCol+=c;
j++;
}
if(!szCol.IsEmpty())
{
if(nCol < TABLE_MAXCOL-1)
{
if(szCol.GetLength() <64)
sprintf(m_Table[nRow].s[nCol],\"%s\",szCol);
nCol++; TRACE(\"szCol=%s\\n\",szCol);
}
}
if(nCol>0)
nRow++;
if(m_nRows >=TABLE_MAXROW)
{
m_nRows=nRow;
return;
}
szLine=\"\";
}
}
else szLine+=cc;
i++;
}
m_nRows=nRow;
}
void test()
{
CDataTxt dt;
dt.m_szPath=\"c:\\\\sqtl.txt\";
dt.Read();
CString szVal,szMsg;
if(dt.GetDefine(\"@COM_PORT\",szVal)){TRACE(\"@COM_PORT=%s\\n\",szVal);}
if(dt.GetDefine(\"@COM_BAUDRATE\",szVal)){TRACE(\"@COM_BAUDRATE=%s\\n\",szVal);}
int i;
for(i=0;i
TRACE(\"Row=%d,ID=%d,s[0]=%s,sz[1]=%s,s[2]=%s,s[3]=%s\\n\",
i,
dt.m_Table.nID,
&(dt.m_Table.s[0][0]),
&(dt.m_Table.s[1][0]),
&(dt.m_Table.s[2][0]),
&(dt.m_Table.s[3][0]));
}
}
文件讀?。?BR> void CShotdetect::WritetoText(int p1, LONGLONG p2)
{
CString str;
str = \"c:\\\\文本文件.txt\";
CFile file;
file.Open(str,CFile::modeCreate|CFile::modeReadWrite|CFile::modeNoTruncate);
char ch_str1[30];
char ch_str2[20];
_itoa(p1,ch_str1,10);
strcat(ch_str1,\",\");
_itoa(p2,ch_str2,10);
strcat(ch_str1,ch_str2);
strcat(ch_str1,\"\\n\");
int length = 0;
for(int i = 0;i<30;i++)
{
if(ch_str1!=’\\0’)
length++;
else
break;
}
file.SeekToEnd();
file.Write(ch_str1,length);
file.Close();