C技巧:VC讀取和分析格式化文本配置文件

字號:

大多數(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();