zoukankan      html  css  js  c++  java
  • 一个基于STL的ini文件解析类,测试通过

    windows平台自带ini解析的接口,但是如果要跨平台的话,就要自己来实现一个,网上找了下,发现在跨平台不够理想

    遂自己修改了一个出来。支持解析utf-8, unicode big endian, unicode little endian格式文件,请勿使用windows的

    ansi保存的文件测试。文件操作时,空格和注释会被丢弃,可能下次有空考虑加上来吧。

    代码如下:

     1 //head file
     2 
     3 #ifndef IniParser_
     4 #define IniParser_
     5 
     6 #include <vector>
     7 #include <string>
     8 #include <map>
     9 
    10 class IniParser
    11 {
    12 public:
    13     IniParser();
    14     ~IniParser();
    15 protected:
    16     typedef unsigned char Byte;
    17     typedef std::map<std::string, std::string> KeyVector;
    18     typedef std::map<std::string, KeyVector> SectionVector;
    19     enum FileEncode {
    20         Unknow_Encode,
    21         Unicode_BE,
    22         Unicode_LE,
    23         Utf8_Encode,
    24     };
    25 public:
    26     bool Open(const std::string &szIni);
    27     std::string GetPrivateProfileString(const std::string &section, 
    28             const std::string &key);
    29     int GetPrivateProfileInt(const std::string &section, const std::string &key);
    30     bool SetPrivateProfileString(const std::string &section, 
    31             const std::string &key, const std::string &value);
    32     bool SetPrivateProfileInt(const std::string &section, 
    33             const std::string &key, int value);
    34     bool Flush(void);
    35 protected:
    36     bool Parser(const std::string &strbuf);
    37     std::string GetLine(void);
    38     bool IsComment(const std::string &line);
    39     bool IsSection(const std::string &line);
    40     std::string GetKeyValueFromLine(const std::string &line);
    41     std::string GetKeyNameFromLine(const std::string &line);
    42     std::string GetSectionNameFromLine(const std::string &line);
    43     std::string RemoveSpace(const std::string &strbuf);
    44     void ResetOffset();
    45     bool IsOffsetEnd();
    46 private:
    47     FileEncode m_encode;
    48     std::string m_strIni;
    49     std::string m_fileBuff;
    50     std::string::size_type m_offset;
    51     SectionVector m_mpValue;
    52 };
    53 
    54 #endif
      1 // source file
      2 
      3 #include <fstream>
      4 #include <iostream>
      5 #include <algorithm>
      6 #include <deque>
      7 #include <sstream>
      8 #include "IniParser.h"
      9 
     10 // Convert Unicode big endian to Unicode little endian
     11 static unsigned Ucs2BeToUcs2Le(unsigned short *ucs2bige, unsigned int size)
     12 {
     13     printf("@ %s %d line\n", __FUNCTION__, __LINE__);
     14 
     15     if (!ucs2bige) {
     16         return 0;
     17     }
     18     
     19     unsigned int length = size;
     20     unsigned short *tmp = ucs2bige;
     21     
     22     while (*tmp && length) {
     23         
     24         length--;
     25         unsigned char val_high = *tmp >> 8;
     26         unsigned char val_low = (unsigned char)*tmp;
     27         
     28         *tmp = val_low << 8 | val_high;
     29         
     30         tmp++;
     31     }
     32     
     33     return size - length;
     34 }
     35 
     36 // Convert Unicode little endian to Unicode big endian
     37 static unsigned Ucs2LeToUcs2Be(unsigned short *ucs2le, unsigned int size)
     38 {
     39     if (!ucs2le) {
     40         return 0;
     41     }
     42     
     43     printf("@ %s %d line\n", __FUNCTION__, __LINE__);
     44 
     45     unsigned int length = size;
     46     unsigned short *tmp = ucs2le;
     47     
     48     while (*tmp && length) {
     49         
     50         length--;
     51         unsigned char val_high = *tmp >> 8;
     52         unsigned char val_low = (unsigned char)*tmp;
     53         
     54         *tmp = val_low << 8 | val_high;
     55         
     56         tmp++;
     57     }
     58     
     59     return size - length;
     60 }
     61 
     62 // Convert Ucs-2 to Utf-8
     63 static unsigned int Ucs2ToUtf8(unsigned short *ucs2, unsigned int ucs2_size, 
     64                         unsigned char *utf8, unsigned int utf8_size)
     65 {
     66     unsigned int length = 0;
     67     
     68     if (!ucs2) {
     69         return 0;
     70     }
     71     
     72     unsigned short *inbuf = ucs2;
     73     unsigned char *outbuf = utf8;
     74     
     75     if (*inbuf == 0xFFFE) {
     76         Ucs2BeToUcs2Le(inbuf, ucs2_size);
     77     }
     78     
     79     if (!utf8) {
     80         unsigned int insize = ucs2_size;
     81         
     82         while (*inbuf && insize) {
     83             insize--;
     84             
     85             if (0x0080 > *inbuf) {
     86                 length++;
     87             } else if (0x0800 > *inbuf) {
     88                 length += 2;                
     89             } else {
     90                 length += 3;
     91             }
     92             
     93             inbuf++;
     94         }
     95         return length;
     96         
     97     } else {        
     98         unsigned int insize = ucs2_size;
     99         
    100         while (*inbuf && insize && length < utf8_size) {            
    101             insize--;
    102             
    103             if (*inbuf == 0xFFFE) {
    104                 inbuf++;
    105                 continue;
    106             }
    107             
    108             if (0x0080 > *inbuf) {
    109                 /* 1 byte UTF-8 Character.*/
    110                 *outbuf++ = (unsigned char)(*inbuf);
    111                 length++;
    112             } else if (0x0800 > *inbuf) {
    113                 /*2 bytes UTF-8 Character.*/
    114                 *outbuf++ = 0xc0 | ((unsigned char)(*inbuf >> 6));
    115                 *outbuf++ = 0x80 | ((unsigned char)(*inbuf & 0x3F));
    116                 length += 2;
    117                 
    118             } else {
    119                 /* 3 bytes UTF-8 Character .*/
    120                 *outbuf++ = 0xE0 | ((unsigned char)(*inbuf >> 12));
    121                 *outbuf++ = 0x80 | ((unsigned char)((*inbuf >> 6) & 0x3F));
    122                 *outbuf++ = 0x80 | ((unsigned char)(*inbuf & 0x3F));
    123                 length += 3; 
    124             }
    125             
    126             inbuf++;
    127         }
    128         
    129         return length;
    130     }
    131 }
    132 
    133 //// Convert Ucs-2 to Utf-8
    134 static unsigned int Utf8ToUcs2(unsigned char *utf8, unsigned int utf8_size, 
    135                         unsigned short *ucs2, unsigned int ucs2_size)
    136 {
    137     int length = 0;
    138     unsigned int insize = utf8_size;
    139     unsigned char *inbuf = utf8;
    140     
    141     if(!utf8)
    142         return 0;
    143     
    144     if(!ucs2) {
    145         while(*inbuf && insize) {
    146             unsigned char c = *inbuf;
    147             if((c & 0x80) == 0) {
    148                 length += 1;
    149                 insize -= 1;
    150                 inbuf++;
    151             }
    152             else if((c & 0xE0) == 0xC0) {
    153                 length += 1;
    154                 insize -= 2;
    155                 inbuf += 2;
    156             } else if((c & 0xF0) == 0xE0) {
    157                 length += 1;
    158                 insize -= 3;
    159                 inbuf += 3;
    160             }
    161         }
    162         return length;
    163         
    164     } else {
    165         unsigned short *outbuf = ucs2;
    166         unsigned int outsize = ucs2_size;
    167         
    168         while(*inbuf && insize && length < outsize) {
    169             unsigned char c = *inbuf;
    170             if((c & 0x80) == 0) {
    171                 *outbuf++ = c;
    172                 inbuf++;
    173                 length++;
    174                 insize--;
    175             } else if((c & 0xE0) == 0xC0) {
    176                 unsigned short val;
    177                 
    178                 val = (c & 0x3F) << 6;
    179                 inbuf++;
    180                 c = *inbuf;
    181                 val |= (c & 0x3F);
    182                 inbuf++;
    183                 
    184                 length++;
    185                 insize -= 2;
    186                 
    187                 *outbuf++ = val;
    188             } else if((c & 0xF0) == 0xE0) {
    189                 unsigned short val;
    190                 
    191                 val = (c & 0x1F) << 12;
    192                 inbuf++;
    193                 c = *inbuf;
    194                 val |= (c & 0x3F) << 6;
    195                 inbuf++;
    196                 c = *inbuf;
    197                 val |= (c & 0x3F);
    198                 inbuf++;
    199                 
    200                 insize -= 3;
    201                 length++;
    202                 
    203                 *outbuf++ = val;
    204             }
    205         }
    206         return length;
    207     }
    208     return 0;
    209 }
    210 
    211 IniParser::IniParser()
    212 : m_strIni("")
    213 , m_fileBuff("")
    214 , m_offset(0)
    215 , m_encode(Unknow_Encode)
    216 {
    217 }
    218 
    219 IniParser::~IniParser()
    220 {
    221 }
    222 
    223 bool IniParser::Open(const std::string &szIni)
    224 {
    225     m_strIni = szIni;
    226     
    227     if (m_strIni.empty()) {
    228         return false;
    229     }
    230     
    231     std::ifstream infile(m_strIni.c_str());
    232     if (!infile) {
    233         return false;
    234     }
    235     
    236     infile.seekg(0, std::ios::end);
    237     unsigned length = infile.tellg();
    238     infile.seekg(0, std::ios::beg);
    239     
    240     if (length < 3) {
    241         return false;
    242     }
    243     
    244     unsigned int buff_size = length / sizeof(unsigned short) + 1;
    245     unsigned short *buff = new unsigned short[buff_size];
    246     infile.read((char *)buff, length);
    247     buff[buff_size] = '\0';
    248     
    249     unsigned char *utf8 = NULL;
    250     
    251     // support unicode & utf-8 encode
    252     if (*buff == 0xFEFF || *buff == 0xFFFE) {
    253 
    254         if (*buff == 0xFEFF) {
    255             m_encode = Unicode_LE;
    256         } else {
    257             m_encode = Unicode_BE;
    258         }
    259 
    260         unsigned int utf8_size = Ucs2ToUtf8(buff, buff_size, utf8, 0);
    261         utf8 = new unsigned char [utf8_size + 1];
    262         Ucs2ToUtf8(buff, buff_size, utf8, utf8_size);
    263 
    264         delete [] buff;
    265 
    266     } else if (*(unsigned char *)buff == 0xEF && *((unsigned char *)buff + 1) == 0xBB 
    267                && *((unsigned char *)buff + 2) == 0xBF) {
    268 
    269         utf8 = (unsigned char *)buff;
    270         m_encode = Utf8_Encode;
    271 
    272     } else {
    273 
    274         delete [] buff;
    275         return false;
    276     }
    277     
    278     m_fileBuff = (char *)utf8;
    279     
    280     delete [] utf8;
    281     infile.close();
    282     
    283     return Parser(m_fileBuff);    
    284 }
    285 
    286 bool IniParser::IsSection(const std::string &line)
    287 {
    288     std::string::size_type stLeft = line.find("[");
    289     std::string::size_type stRight = line.find("]");
    290     
    291     if (!line.empty() && stLeft != std::string::npos && 
    292             stRight != std::string::npos && stRight > stLeft) {
    293         return true;
    294     }
    295     
    296     return false;
    297 }
    298 
    299 std::string IniParser::GetSectionNameFromLine(const std::string &line)
    300 {
    301     std::string::size_type stLeft = line.find("[");
    302     std::string::size_type stRight = line.find("]");
    303     
    304     if (!line.empty() && stLeft != std::string::npos && 
    305             stRight != std::string::npos && stRight > stLeft) {
    306         std::string section(line, stLeft + 1, stRight - stLeft - 1);
    307         return RemoveSpace(section);
    308     }
    309     
    310     return std::string();
    311 }
    312 
    313 std::string IniParser::RemoveSpace(const std::string &strbuf)
    314 {
    315     std::string stReturn = strbuf;
    316 
    317     if(strbuf.empty())
    318         return stReturn;
    319 
    320     std::string::size_type stLeft = 0;
    321     std::string::size_type stRight = 0;
    322     stLeft = strbuf.find_first_not_of(' ');
    323     stRight = strbuf.find_last_not_of(' ');
    324 
    325     if(stLeft == std::string::npos || stRight == std::string::npos)
    326         return stReturn;
    327 
    328     std::string st(strbuf, stLeft, stRight - stLeft + 1);
    329     return st;
    330 }
    331 
    332 std::string IniParser::GetKeyNameFromLine(const std::string &line)
    333 {
    334     std::string::size_type stpos = line.find("=");
    335     if (stpos == 0) {
    336         return std::string();
    337     }
    338     
    339     std::string strbuf;
    340     if (stpos == std::string::npos) {
    341         strbuf = line;
    342     } else {
    343         strbuf.clear();
    344         strbuf.insert(0, line, 0, stpos);
    345     }
    346     
    347     return RemoveSpace(strbuf);
    348 }
    349 
    350 std::string IniParser::GetKeyValueFromLine(const std::string &line)
    351 {
    352     std::string::size_type stpos = line.find("=");
    353     if (stpos == std::string::npos) {
    354         return std::string();
    355     }
    356     
    357     std::string strbuf;
    358     strbuf.clear();
    359     strbuf.insert(0, line, stpos + 1, line.size());
    360     
    361     return RemoveSpace(strbuf);
    362 }
    363 
    364 bool IniParser::Parser(const std::string &strbuf)
    365 {
    366     ResetOffset();
    367     
    368     KeyVector mpKey;
    369     std::string section;
    370     
    371     while (true) {
    372         std::string line = GetLine();
    373         if (line.empty() || IsComment(line)) {
    374             if (IsOffsetEnd()) {
    375                 break;
    376             } else {
    377                 continue;
    378             }
    379         }
    380         
    381         if (IsSection(line)) {
    382             if (section.empty()) {
    383                 section = GetSectionNameFromLine(line);
    384                 continue;
    385             } 
    386             
    387             m_mpValue.insert(std::make_pair(section, mpKey));
    388             section = GetSectionNameFromLine(line);
    389             mpKey.clear();
    390         } else {
    391             if (section.empty()) {
    392                 continue;
    393             }
    394             std::string strKey = GetKeyNameFromLine(line);
    395             if (!strKey.empty()) {
    396                 mpKey.insert(std::make_pair(strKey, GetKeyValueFromLine(line)));
    397             }
    398         }
    399     }
    400     
    401     if (!section.empty()) {
    402         m_mpValue.insert(std::make_pair(section, mpKey));
    403     }
    404 
    405     return true;
    406 }
    407 
    408 std::string IniParser::GetLine()
    409 {
    410     std::string line;
    411     if (m_offset >= m_fileBuff.size()) {
    412         return std::string();
    413     }
    414     
    415     std::string::size_type stPos = m_fileBuff.find("\r\n", m_offset);
    416     if (stPos == std::string::npos) {
    417         line.insert(0, m_fileBuff, m_offset, m_fileBuff.size() - m_offset + 1);
    418         m_offset = m_fileBuff.size() + 1;
    419     } else {
    420         line.insert(0, m_fileBuff, m_offset, stPos - m_offset);
    421         m_offset = stPos + 2;
    422     }
    423     
    424     return line;
    425 }
    426 
    427 void IniParser::ResetOffset()
    428 {
    429     m_offset = 0;
    430 }
    431 
    432 bool IniParser::IsOffsetEnd()
    433 {
    434     if (m_offset >= m_fileBuff.size()) {
    435         return true;
    436     }
    437     return false;
    438 }
    439 
    440 bool IniParser::IsComment(const std::string &line)
    441 {
    442     if (line.empty() || line[0] == ';') {
    443         return true;
    444     }
    445     
    446     return false;
    447 }
    448 
    449 /*
    450 std::string IniParser::ConvertToLowercase(const std::string &strBuf)
    451 {
    452     std::string str = strBuf;
    453     std::transform(str.begin(), str.end(), str.begin(), tolower);
    454     return str;
    455 }
    456 */
    457 
    458 std::string IniParser::GetPrivateProfileString(const std::string &section, 
    459         const std::string &key)
    460 {
    461     if (m_mpValue.empty() || section.empty() || key.empty()) {
    462         return std::string();
    463     }
    464     
    465     for (SectionVector::iterator iter_section = m_mpValue.begin(); 
    466             iter_section != m_mpValue.end(); iter_section++) {
    467         if (section == iter_section->first) {
    468             for (KeyVector::iterator iter_key = iter_section->second.begin(); 
    469                  iter_key != iter_section->second.end(); iter_key++) {
    470                 if (key == iter_key->first) {
    471                     return iter_key->second;
    472                 }
    473             }
    474         }
    475     }
    476 
    477     return std::string();
    478 }
    479 
    480 bool IniParser::SetPrivateProfileString(const std::string &section, 
    481         const std::string &key, const std::string &value)
    482 {
    483     for (SectionVector::iterator iter_section = m_mpValue.begin(); 
    484             iter_section != m_mpValue.end(); iter_section++) {
    485         if (section == iter_section->first) {
    486             //find exist section
    487             for (KeyVector::iterator iter_key = iter_section->second.begin(); 
    488                     iter_key != iter_section->second.end(); iter_key++) {
    489                 if (key == iter_key->first) {
    490                     // find exist key
    491                     iter_key->second = value;
    492                     return true;
    493                 }
    494             }
    495             
    496             // add new key
    497             std::cout << "new key " << key << " in" << std::endl;
    498             iter_section->second.insert(std::make_pair(key, value));
    499             return true;
    500         }
    501     }
    502     
    503     //add new section
    504     KeyVector mpKey;
    505     mpKey.insert(std::make_pair(key, value));
    506     m_mpValue.insert(std::make_pair(section, mpKey));
    507     return true;
    508 }
    509 
    510 bool IniParser::SetPrivateProfileInt(const std::string &section, 
    511         const std::string &key, int value)
    512 {
    513     std::stringstream ss;
    514     ss << value;
    515     
    516     std::string str_value;
    517     ss >> str_value;
    518     
    519     return SetPrivateProfileString(section, key, str_value);
    520 }
    521 
    522 int IniParser::GetPrivateProfileInt(const std::string &section, 
    523         const std::string &key)
    524 {
    525     return atoi(GetPrivateProfileString(section, key).c_str());
    526 }
    527 
    528 bool IniParser::Flush()
    529 {
    530     if (m_encode == Unknow_Encode) {
    531         return false;
    532     }
    533     
    534     std::ofstream outfile(m_strIni.c_str(), 
    535             std::ofstream::binary | std::ofstream::trunc);
    536     if (!outfile) {
    537         std::cout << "Open file " << m_strIni << " failed." << std::endl;
    538         return false;
    539     }
    540     
    541     m_fileBuff.clear();
    542     for (SectionVector::iterator iter_section = m_mpValue.begin(); 
    543             iter_section != m_mpValue.end(); iter_section++) {
    544         m_fileBuff += "[";
    545         m_fileBuff += iter_section->first;
    546         m_fileBuff += "]\r\n";
    547         
    548         for (KeyVector::iterator iter_key = iter_section->second.begin(); 
    549                 iter_key != iter_section->second.end(); iter_key++) {
    550             m_fileBuff += iter_key->first;
    551             m_fileBuff += "=";
    552             m_fileBuff += iter_key->second;
    553             m_fileBuff += "\r\n";
    554         }
    555         m_fileBuff += "\r\n";
    556     }
    557     
    558     unsigned char file_head[3];
    559     
    560     if (m_encode == Utf8_Encode) {
    561         file_head[0] = 0xEF; file_head[1] = 0xBB; file_head[2] = 0xBF;
    562         
    563         outfile.write((char *)file_head, 3);
    564         outfile.write(m_fileBuff.c_str(), m_fileBuff.size());
    565         
    566     } else if (m_encode == Unicode_BE) {
    567         unsigned short *ucs2buf = NULL;
    568         unsigned int ucs2_size = Utf8ToUcs2((unsigned char *)m_fileBuff.c_str(), 
    569                 m_fileBuff.size(), ucs2buf, 0);
    570         ucs2buf = new unsigned short [ucs2_size];
    571         Utf8ToUcs2((unsigned char *)m_fileBuff.c_str(), m_fileBuff.size(), 
    572                 ucs2buf, ucs2_size);
    573         Ucs2LeToUcs2Be(ucs2buf, ucs2_size);
    574         
    575         file_head[0] = 0xFE; file_head[1] = 0xFF;
    576         
    577         outfile.write((char *)file_head, 2);
    578         outfile.write((char *)ucs2buf, ucs2_size * sizeof(unsigned short));
    579         
    580         delete ucs2buf;
    581     } else if (m_encode == Unicode_LE) {
    582         unsigned short *ucs2buf = NULL;
    583         unsigned int ucs2_size = Utf8ToUcs2((unsigned char *)m_fileBuff.c_str(), 
    584                 m_fileBuff.size(), ucs2buf, 0);
    585         ucs2buf = new unsigned short [ucs2_size];
    586         Utf8ToUcs2((unsigned char *)m_fileBuff.c_str(), m_fileBuff.size(), 
    587                 ucs2buf, ucs2_size);
    588                 
    589         file_head[0] = 0xFF; file_head[1] = 0xFE;
    590         
    591         outfile.write((char *)file_head, 2);
    592         outfile.write((char *)ucs2buf, ucs2_size * sizeof(unsigned short));
    593         
    594         delete ucs2buf;
    595     }
    596     
    597     outfile.close();
    598     return true;
    599 }
  • 相关阅读:
    利用进制转换压缩数字
    一个不错的移动政务网站
    系统缓存全解析(转摘)
    GeoDatabase元数据不能编辑的问题“The application is not licensed to perform this operation ”
    RSA算法的分析与实现(转载)
    云计算经济学
    Memcached在Windows操作系统下多实例并存(转载)
    AGS FlexView 与 ArcGIS Server的FeatureLayer交互的过程
    转载>ArcEngine中版本的使用
    基于ArcEngine的地图四着色算法的实现(转载)
  • 原文地址:https://www.cnblogs.com/jojodru/p/2576522.html
Copyright © 2011-2022 走看看