#ifndef _C_EX_API #define _C_EX_API /** @file c_ex_api.h @brief C/C++扩展API */ /************************************************************************************************* 2009-11-14 过滤前后空白符,制表符,换行符改进为通用模板函数 2010-5-22 增加对字节、字和双字取位值的操作函数 2010-6-9 增加wstring,string和tstring类型间相互转换的函数 2010-6-24 因在DOS控制台下发现cout不能输出中文,所以改进了astr2wstr,wstr2astr实现 基本原因是原实现调用setlocale改变了本地区域设置而没有恢复造成的 *************************************************************************************************/ #include <sstream> #include <vector> #include <cassert> #include "tstring.h" using namespace std; /** @class LocaleGuard @brief 区域守卫类 * 用于astr2wstr,wstr2astr函数实现中 */ class LocaleGuard { public: LocaleGuard() { m_loc=locale::global(locale(locale(),"",LC_CTYPE)); } ~LocaleGuard() { locale::global(m_loc); } private: locale m_loc; }; /** @brief StrToHex ASCII版本 @param lpSrc 源字符串或源缓冲区 @param lSize lpSrc指向数据的大小,字节数 @param chTag 显示分隔符,默认为0表示空字符 @return 返回转化后16进制字符串 * lpSrc实际可为指向某块数据的内存指针,lSize则为这块数据的大小,因 * lpSrc不仅限于字符串,所以增加了lSize参数 */ static string StringToHex(const char* lpSrc, long lSize, char chTag = 0) { string strDest; unsigned char* pSrc = (unsigned char*)lpSrc; char buf[2]; //long dwSize = strlen(lpSrc); for (long lIndex = 0; lIndex < lSize; ++lIndex) { unsigned char c0 = *pSrc >> 4; if ( c0 >= 0x0 && c0 <= 0x9) { buf[0] = c0 - 0 + '0'; } else { buf[0] = c0 - 10 + 'A'; } unsigned char c1 = *pSrc++ & 0x0F; if ( c1 >= 0x0 && c1 <= 0x9) { buf[1] = c1 - 0 + '0'; } else { buf[1] = c1 - 10 + 'A'; } strDest += buf[0]; strDest += buf[1]; if (chTag != 0) strDest += chTag; } return strDest; } /** @brief StrToHex UNICODE版本 @param lpSrc 源字符串 @param lSize lpSrc指向数据的大小,字节数 @param chTag 显示分隔符,默认为0表示空字符 @return 返回转化后16进制字符串 * lpSrc实际可为指向某块数据的内存指针,lSize则为这块数据的大小,因 * lpSrc不仅限于字符串,所以增加了lSize参数 */ static wstring StringToHex(const wchar_t* lpSrc, long lSize, wchar_t chTag = 0) { wstring strDest; unsigned char* pSrc = (unsigned char*)lpSrc; char buf[2]; // long dwSize = wcslen(lpSrc) * sizeof(wchar_t); for (long lIndex = 0; lIndex < lSize; ++lIndex) { unsigned char c0 = *pSrc >> 4; if ( c0 >= 0x0 && c0 <= 0x9) { buf[0] = c0 - 0 + '0'; } else { buf[0] = c0 - 10 + 'A'; } unsigned char c1 = *pSrc++ & 0x0F; if ( c1 >= 0x0 && c1 <= 0x9) { buf[1] = c1 - 0 + '0'; } else { buf[1] = c1 - 10 + 'A'; } strDest += (wchar_t)buf[0]; strDest += (wchar_t)buf[1]; if (chTag != 0) strDest += chTag; } return strDest; } /** @brief 多字节转化为宽字符 @param pmbs 多字节型字符串 @param wstr 存放结果的宽字符串 @return true转换成功,false转换失败 */ static bool astr2wstr(const char* pmbs, wstring& wstr) { LocaleGuard lg; size_t size = mbstowcs(0, pmbs, 0); if (-1 == size) return false; wstr.resize(size); size = mbstowcs((wchar_t*)wstr.data(), pmbs, size); if (-1 == size) return false; return true; } /** @brief 宽字符转化为多字节 @param pwcs 宽字符串 @param str 存放结果的多字节字符串 @return true转换成功,false转换失败 */ static bool wstr2astr(const wchar_t* pwcs, string& str) { LocaleGuard lg; size_t size = wcstombs(0, pwcs, 0); if (-1 == size) return false; str.resize(size); size = wcstombs((char*)str.data(), pwcs, size); if (-1 == size) return false; return true; } /** @brief 多字节转化为tstring宏类型 @param pmbs 多字节型字符串 @param tstr 存放结果的tstring类型字符串 @return true转换成功,false转换失败 */ static bool astr2tstr(const char* pmbs,tstring& tstr) { #if defined(_UNICODE)||defined(UNICODE) return astr2wstr(pmbs,tstr); #else tstr = pmbs; return true; #endif } /** @brief 宽字节转化为tstring宏类型 @param pwcs 宽字节型字符串 @param tstr 存放结果的tstring类型字符串 @return true转换成功,false转换失败 */ static bool wstr2tstr(const wchar_t* pwcs,tstring& tstr) { #if defined(_UNICODE)||defined(UNICODE) tstr = pwcs; return true; #else return wstr2astr(pwcs,tstr); #endif } /** @brief tstring宏类型转化为多字节 @param tstr tstring类型字符串 @param str 存放结果的多字节型字符串 @return true转换成功,false转换失败 */ static bool tstr2astr(const tstring& tstr,string& str) { #if (defined(_UNICODE)||defined(UNICODE)) return wstr2astr(tstr.c_str(),str); #else str = tstr; return true; #endif } /** @brief tstring宏类型转化为宽字节 @param tstr tstring类型字符串 @param wstr 存放结果的宽字节型字符串 @return true转换成功,false转换失败 */ static bool tstr2wstr(const tstring& tstr,wstring& wstr) { #if defined(_UNICODE)||defined(UNICODE) wstr = tstr; return true; #else return astr2wstr(tstr.c_str(),wstr); #endif } /** @brief 将字符转化为对应的10进制数整数 ASCII版本 * 若字符不能转化则返回-1 */ static char ConvertHexChar(char ch) { if(ch>='0'&&ch<='9') return ch-0x30; else if(ch>='A'&&ch<='F') return ch-'A'+10; else if(ch>='a'&&ch<='f') return ch-'a'+10; else return -1; } /** @brief 将字符转化为对应的10进制数整数 Unicode版本 * 若字符不能转化则返回-1 */ static char ConvertHexChar(wchar_t wch) { if(wch>=L'0'&&wch<=L'9') return wch - L'0' ; else if(wch >= L'A' && wch <= L'F') return wch - L'A' + 10; else if(wch >= L'a' && wch<= L'f') return wch - L'a' + 10; else return -1; } typedef vector<unsigned char> CByteArrayEx; /** @brief 将字符串转化成对应的16进制数形式 ASCII版本 * 如字符串80 12 34 46 AD FF,对应的就是0x80,0x12,0x34,0x46,0xAD,0xFF 该函数会自动过滤不能转换的字符,可转换字符范围在0--9,a--f,A--F区间 */ static void StringToHex(const string& str, CByteArrayEx& ByteArray) { size_t len = str.length(); char low = -1, high = -1; for (size_t n = 0; n < len; ) { high = ConvertHexChar(str[n++]); if (-1 == high) { continue; } if (n >= len) { ByteArray.push_back(high); break; } low = ConvertHexChar(str[n++]); if (-1 == low) { ByteArray.push_back(high); continue; } ByteArray.push_back(high * 16 + low); } } /** @brief 将字符串转化成对应的16进制数形式 Unicode版本 * 如字符串80 12 34 46 AD FF,对应的就是0x80,0x12,0x34,0x46,0xAD,0xFF 该函数会自动过滤不能转换的字符,可转换字符范围在0--9,a--f,A--F区间 */ static void StringToHex(const wstring& wstr, CByteArrayEx& ByteArray) { size_t len = wstr.length(); char low = -1, high = -1; for (size_t n = 0; n < len; ) { high = ConvertHexChar(wstr[n++]); if (-1 == high) { continue; } if (n >= len) { ByteArray.push_back(high); break; } low = ConvertHexChar(wstr[n++]); if (-1 == low) { ByteArray.push_back(high); continue; } ByteArray.push_back(high*16 + low); } } /** @brief 字符串转化为内置类型 ASCII版本 */ template <class T> static bool from_string(T &t, const string &s, ios_base & (*f)(ios_base&)) { std::istringstream iss(s); return !(iss>>f>>t).fail(); } /** @brief 字符串转化为内置类型 Unicode版本 */ template <class T> static bool from_wstring(T &t, const wstring &s, ios_base & (*f)(ios_base&)) { std::wistringstream iss(s); return !(iss>>f>>t).fail(); } /** @brief 内置类型转化为字符串 ASCII版本 */ template <class T> static std::string to_string(T t, ios_base & (*f)(ios_base&)) { std::ostringstream oss; oss << f << t; return oss.str(); } /** @brief 内置类型转化为字符串 Unicode版本 */ template <class T> static std::wstring to_wstring(T t, ios_base & (*f)(ios_base&)) { std::wostringstream oss; oss << f << t; return oss.str(); } /** @brief 过滤前端空白字符,制表符,换行符 */ template<typename T> static void TrimLeft(basic_string<T>& bstr) { for(basic_string<T>::iterator iter = bstr.begin(); iter != bstr.end(); ) { if (*iter == (T)' '||*iter == (T)'/t'||*iter == (T)'/r'||*iter == (T)'/n') { iter = bstr.erase(iter); } else { break; } } } /** @brief 过滤后端空白字符,制表符,换行符 */ template<typename T> static void TrimRight(basic_string<T>& bstr) { for (basic_string<T>::reverse_iterator r_iter = bstr.rbegin(); r_iter != bstr.rend(); ) { if (*r_iter == (T)' '||*r_iter == (T)'/t'||*r_iter == (T)'/r'||*r_iter == (T)'/n') { r_iter = basic_string<T>::reverse_iterator(bstr.erase(r_iter.base() - 1)); } else { break; } } } /** @brief 过滤前后端空白字符,制表符,换行符 */ template<typename T> static void Trim(basic_string<T>& bstr) { TrimLeft(bstr); TrimRight(bstr); } static inline ostream& operator << (ostream& os, const tstring& tstr) { #if defined(_UNICODE)||defined(UNICODE) string str; wstr2astr(tstr.c_str(), str); return os << str; #else return os << tstr.c_str(); #endif } static inline wostream& operator << (wostream& wos, const tstring& tstr) { #if defined(_UNICODE)||defined(UNICODE) return wos << tstr.c_str(); #else wstring wstr; astr2wstr(tstr.c_str(), wstr); return wos << wstr; #endif } /** @brief 按标记找出子串 */ static vector<string> tokenize(const string& src, string tok,bool trim=false, string null_subst="") { if( src.empty() || tok.empty() ) throw "tokenize: empty string"; vector<string> v; size_t pre_index = 0, index = 0, len = 0; while( (index = src.find_first_of(tok, pre_index)) != string::npos ) { if( (len = index-pre_index)!=0 ) v.push_back(src.substr(pre_index, len)); else if(trim==false) v.push_back(null_subst); pre_index = index+1; } string endstr = src.substr(pre_index); if( trim==false ) v.push_back( endstr.empty()?null_subst:endstr ); else if( !endstr.empty() ) v.push_back(endstr); return v; } /** @brief 按标记分隔字符串 */ static vector<string> split(const string& src, string delimit, string null_subst="") { if( src.empty() || delimit.empty() ) throw "split:empty string"; vector<string> v; size_t deli_len = delimit.size(); long index = string::npos, last_search_position = 0; while( (index=src.find(delimit,last_search_position))!= string::npos ) { if(index==last_search_position) v.push_back(null_subst); else v.push_back( src.substr(last_search_position, index-last_search_position) ); last_search_position = index + deli_len; } string last_one = src.substr(last_search_position); v.push_back( last_one.empty()? null_subst:last_one ); return v; } /** @brief 获取一个字节的某位值 @return 返回结果值或为1,或为0 */ static int get_byte_bit(char val, int bit) { assert(bit >= 1 && bit <= 8); return (val >> (bit - 1)) & 0x01; } /** @brief 获取一个字的某位值 @return 返回结果值或为1,或为0 */ static int get_word_bit(short val, int bit) { assert(bit >= 1 && bit <= 16); if (bit <= 8) { return get_byte_bit(val&0xFF,bit); } else { return get_byte_bit(val>>8,bit-8); } } /** @brief 获取一个双字的某位值 @return 返回结果值或为1,或为0 */ static int get_dword_bit(long val, int bit) { assert(bit >= 1 && bit <= 32); if (bit <= 16) { return get_word_bit(val&0xFFFF,bit); } else { return get_word_bit(val>>16,bit-16); } } /** @brief 判断机器字节序 @return 返回true,则为大端序(big endian);否则为小端序(little endian) */ static bool is_big_endian() { short val = 0x00FF; char* p = (char*)&val; if (*p == (char)0xFF) return false; else return true; } #endif #ifndef _TSTRING_H #define _TSTRING_H #include <string> using namespace std; #ifndef tstring #if (defined(_UNICODE)||defined(UNICODE)) typedef wstring tstring; #define text(x) L ## x #else typedef string tstring; #define text(x) x #endif #endif #endif #ifndef _INI_FILE_H #define _INI_FILE_H #include <stdio.h> #include <tchar.h> #include <Windows.h> #include <map> #include "tstring.h" #include "c_ex_api.h" #include <vector> //STL动态数组 using namespace std; // class CIniFile { public: struct LineInfo { string strSectionName;//store the SectionName string strKey;//store the key string strValue;//store the value long lngDataFlag; //point out judge }; typedef struct SectionNode { string strName; long lIndex; long endofline; SectionNode(/*const string& _strName,long _lIndex*/) //:strName(_strName),lIndex(_lIndex) { strName.clear(); lIndex = 0; endofline = 1; } void ClearNode(){strName.clear(),lIndex = 0;} bool operator < (const SectionNode& Sec) const { return lIndex < Sec.lIndex; } } KeyNode; typedef map<KeyNode, string> KeyMap; //KeyMap: key(string) = value(string) typedef map<SectionNode, KeyMap> IniMap; //Section(string): KeyMap1/KeyMap2/...... public: void Clearm_IniMap(); IniMap::iterator m_IniMapBegin(); IniMap::iterator m_IniMapEnd(); private: /*存储整个文件内容*/ IniMap m_IniMap; //Read IniFile store in IniMap enum enFileType //enum file type { Type_INVALID = -1,//inexistence Type_ANSI = 0, // Ansi Type_Lit_UNICODE = 1,// Unicode Type_big_UNICODE = 2, }; enum enCR_or_LF { CR_and_LF = 1, Only_CR = 2, Only_LF = 3, }; public: CIniFile(); virtual ~CIniFile(); //添加、删除一个节或键 bool AddSectionA(const string& strSectionName);//添加节 bool DeleteSectionA(const string& strSectionName);//删除节 bool AddKeyA(const string& strSectionName, const string& strKeyName);//添加键 bool DeleteKeyA(const string& strSectionName, const string& strKeyName);//删除键 bool AddSectionW(const wstring& wtrSectionName); bool DeleteSectionW(const wstring& wtrSectionName); bool AddKeyW(const wstring& wtrSectionName, const wstring& wtrKeyName); bool DeleteKeyW(const wstring& wtrSectionName, const wstring& wtrKeyName); //获取一个键值,需要相应的节名、键名 void GetSectionNameA(vector<string>& strSectionName); void GetSectionNameW(vector<wstring>& wtrSectionName); long GetLongValueA(const string& strSectionName, const string& strKeyName); double GetDoubleValueA(const string& strSectionName, const string& strKeyName); string GetStringValueA(const string& strSectionName, const string& strKeyName); long GetLongValueW(const wstring& wtrSectionName, const wstring& wtrKeyName); double GetDoubleValueW(const wstring& wtrSectionName, const wstring& wtrKeyName); wstring GetStringValueW(const wstring& wtrSectionName, const wstring& wtrKeyName); //制定相对应的节名、键名才能设置相应的值 bool SetLongValueA(const string& strSectioName, const string& strKeyName, long lngValue); bool SetDoubleValueA(const string& strSectionName, const string& strKeyName, double fValue); bool SetStringValueA(const string& strSectionName, const string& strKeyName, const string& strValue); bool SetLongValueW(const wstring& wtrSectioName, const wstring& wtrKeyName, long lngValue); bool SetDoubleValueW(const wstring& wtrSectionName, const wstring& wtrKeyName, double fValue); bool SetStringValueW(const wstring& wtrSectionName, const wstring& wtrKeyName, const wstring& wtrValue); #if (!defined(UNICODE) && !defined(_UNICODE)) #define GetSectionName GetSectionNameA #define AddKey AddKeyA #define DeleteKey DeleteKeyA #define AddSection AddSectionA #define DeleteSection DeleteSectionA #define GetLongValue GetLongValueA #define GetDoubleValue GetDoubleValueA #define GetStringValue GetStringValueA #define SetLongValue SetLongValueA #define SetDoubleValue SetDoubleValueA #define SetStringValue SetStringValueA #define Open OpenA #define SaveAs SaveAsA #else #define GetSectionName GetSectionNameW #define AddKey AddKeyW #define DeleteKey DeleteKeyW #define AddSection AddSectionW #define DeleteSection DeleteSectionW #define GetLongValue GetLongValueW #define GetDoubleValue GetDoubleValueW #define GetStringValue GetStringValueW #define SetLongValue SetLongValueW #define SetDoubleValue SetDoubleValueW #define SetStringValue SetStringValueW #define Open OpenW #define SaveAs SaveAsW #endif void Printf(bool bDosOrWin32 = true);//test function //打开文件并读取整个文件内容 bool OpenA(LPCSTR lpFileName); bool OpenW(LPCWSTR lpFileName); bool SaveAsA(LPCSTR lpFileName, int /*enFileType*/ emFileType=Type_ANSI);//write the map data to the file bool SaveAsW(LPCWSTR lpFileName, int /*enFileType*/ emFileType=Type_ANSI); bool Save(); //保存到当前文件中 private: bool GetLineA(string& strline);//read ANSI file a line bool GetLineW(wstring& wstrline);//read Unicode file a line bool ParseLine(string strline, LineInfo& lineInfoA);//judge a line is Section or Key=value CIniFile::enFileType GetFileType();//return the IniFile type Ansi or Unicode bool endoffile();//判断是否读到文件末尾 HANDLE m_hIniFile;//the handl of file LPCTSTR m_lpFilePath;//存储文件路径 enFileType m_FileType;//判断文件类型 enCR_or_LF m_CR_or_LF;//判断文件结尾类型 }; #endif #include "inifile.h" #include <iostream> #include <cassert> // CIniFile::CIniFile() { m_lpFilePath = NULL; m_hIniFile = INVALID_HANDLE_VALUE; m_CR_or_LF = CR_and_LF; } CIniFile::~CIniFile() { m_IniMap.clear(); } bool CIniFile::endoffile() { assert(INVALID_HANDLE_VALUE != m_hIniFile); DWORD dwCurLow = SetFilePointer(m_hIniFile,0,NULL,FILE_CURRENT); DWORD dwEndLow = SetFilePointer(m_hIniFile,0,NULL,FILE_END); bool bEof = (dwCurLow == dwEndLow); SetFilePointer(m_hIniFile,dwCurLow,NULL,FILE_BEGIN); return bEof; } void CIniFile::Clearm_IniMap() { m_IniMap.clear(); } CIniFile::IniMap::iterator CIniFile::m_IniMapBegin() { return m_IniMap.begin(); } CIniFile::IniMap::iterator CIniFile::m_IniMapEnd() { return m_IniMap.end(); } // bool CIniFile::GetLineA(string& strline) { strline.clear();//=_T(""); char cTempChar = _T(' ');//interim store a character DWORD dwBytesRead = 1;//have read a char yet bool bReadResult = false; while(!endoffile()) { bReadResult = ReadFile(m_hIniFile, (void*)&cTempChar, 1, &dwBytesRead, NULL); if (bReadResult && (dwBytesRead!=0)) { strline += cTempChar; } if(cTempChar == '\r') { bReadResult = ReadFile(m_hIniFile, (void*)&cTempChar, 1, &dwBytesRead, NULL); if (bReadResult && (dwBytesRead!=0)) { if(cTempChar == '\n') { m_CR_or_LF = CR_and_LF; } else { SetFilePointer(m_hIniFile,-1,NULL,FILE_CURRENT); m_CR_or_LF = Only_CR; } break; } } else if (cTempChar == '\n') { m_CR_or_LF = Only_LF; break; } } return true; } bool CIniFile::GetLineW(wstring& wstrline) { wstrline.clear(); wchar_t wcTempChar = L'';//interim store a character DWORD dwBytesRead = 2;//have read a char yet bool bReadResult = false, bIsSwap = false; if ((is_big_endian()&&(m_FileType == Type_Lit_UNICODE))/*机器为大端文件为小端*/||(!is_big_endian()&&(m_FileType == Type_big_UNICODE))/*机器为小端文件为大端*/) { bIsSwap = true;//需要交换高低字节值 } while(!endoffile()) { bReadResult = ReadFile(m_hIniFile, (void*)&wcTempChar, 2, &dwBytesRead, NULL); if (bReadResult && (dwBytesRead!=0)) { if (bIsSwap) { char * pH = (char*)&wcTempChar; char * pL = pH + 1; swap(*pH,*pL); } wstrline += wcTempChar; } if(wcTempChar == L'\r') { bReadResult = ReadFile(m_hIniFile, (void*)&wcTempChar, 2, &dwBytesRead, NULL); if (bReadResult && (dwBytesRead!=0)) { if (bIsSwap) { char * pH = (char*)&wcTempChar; char * pL = pH + 1; swap(*pH,*pL); } if (wcTempChar == L'\n') { m_CR_or_LF = CR_and_LF; } else { SetFilePointer(m_hIniFile,-2,NULL,FILE_CURRENT); m_CR_or_LF = Only_CR; } break; } } else if (wcTempChar == L'\n') { m_CR_or_LF = Only_LF; break; } } return true; } // bool CIniFile::ParseLine(string strline, LineInfo& lineInfo) { Trim(strline); long lngpos1 = strline.find('['), lngpos2 = strline.rfind(']')+1; long lngpos3 = strline.find('='); if (lngpos1==0 && lngpos2 == strline.length())//This line is section { lineInfo.lngDataFlag = 1; lineInfo.strSectionName = strline.substr(lngpos1+1, lngpos2-2); return true; } if (lngpos3 != -1)//This line is key and value { lineInfo.lngDataFlag = 2; lineInfo.strKey = strline.substr(0, lngpos3); lineInfo.strValue = strline.substr(lngpos3+1, strline.length()); return true; } lineInfo.lngDataFlag = -1; lineInfo.strSectionName.clear(),lineInfo.strKey.clear(),lineInfo.strValue.clear(); return false; } // bool CIniFile::Open(LPCTSTR lpFileName) { KeyMap key_map; SectionNode SectionName_Node; KeyNode Key_Node; bool bIs_litt_UnicodeOr_big = false;//默认格式为ANSCI string strline; wstring wstrline; LineInfo lineInfo; long lisfirstline = 0; m_hIniFile= CreateFile(lpFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (m_hIniFile == INVALID_HANDLE_VALUE) { return false; } m_lpFilePath = lpFileName; m_FileType = GetFileType(); if (m_FileType == Type_Lit_UNICODE||m_FileType == Type_big_UNICODE)//The file is Unicode { bIs_litt_UnicodeOr_big = true; SetFilePointer(m_hIniFile, 2, NULL, FILE_BEGIN); } while (!endoffile()) { if (!bIs_litt_UnicodeOr_big) { GetLineA(strline); } if (bIs_litt_UnicodeOr_big) { GetLineW(wstrline); wstr2astr(wstrline.c_str(), strline); } lisfirstline++; ParseLine(strline, lineInfo); if (1 == lineInfo.lngDataFlag) { if( lisfirstline ==1 )//通常第一行为节,如果为第一行,暂时不处理 { if (lineInfo.strSectionName.length() != 0) { SectionName_Node.strName = lineInfo.strSectionName; SectionName_Node.lIndex += 1; SectionName_Node.endofline = m_CR_or_LF; } } if (SectionName_Node.strName != lineInfo.strSectionName || endoffile() == true)//遇到新的节 { if (SectionName_Node.strName.length()!=0) { m_IniMap[SectionName_Node]=key_map; } SectionName_Node.strName = lineInfo.strSectionName; SectionName_Node.lIndex += 1; SectionName_Node.endofline = m_CR_or_LF; Key_Node.ClearNode(); key_map.clear(); } } else if (2 == lineInfo.lngDataFlag)//键和值 { Key_Node.strName = lineInfo.strKey; Key_Node.lIndex += 1; Key_Node.endofline = m_CR_or_LF; key_map[Key_Node] = lineInfo.strValue; } } if (SectionName_Node.strName.length() != 0) { m_IniMap[SectionName_Node] = key_map; key_map.clear(); } CloseHandle(m_hIniFile); return true; } // CIniFile::enFileType CIniFile::GetFileType() { char pBuf[2]; DWORD dwReaded; enFileType type; if (ReadFile(m_hIniFile,pBuf,sizeof(pBuf),&dwReaded,0) && sizeof(pBuf) == dwReaded) { if (pBuf[0]==(char)0xFF && pBuf[1]==(char)0xFE) { type = Type_Lit_UNICODE; } else if (pBuf[0]==(char)0xFE && pBuf[1]==(char)0xFF) { type = Type_big_UNICODE; } else { type = Type_ANSI; } } else { SetFilePointer(m_hIniFile,0,NULL,FILE_BEGIN);//重新设置读取文件位置为文件开始 return Type_INVALID; } SetFilePointer(m_hIniFile,0,NULL,FILE_BEGIN); return type; } // void CIniFile::GetSectionNameA(vector<string>& strSectionName) { IniMap::iterator pos; KeyMap::iterator poskey; if (!m_IniMap.empty()) { for (pos = m_IniMap.begin();pos != m_IniMap.end(); ++pos) { if ((pos->first).strName != "") strSectionName.push_back((pos->first).strName); } } } void CIniFile::GetSectionNameW(vector<wstring>& strSectionName) { wstring wtrSectionName; string strTemp; IniMap::iterator pos; KeyMap::iterator poskey; if (!m_IniMap.empty()) { for (pos = m_IniMap.begin();pos != m_IniMap.end(); ++pos) { if ((pos->first).strName != "") { strTemp = (pos->first).strName; astr2wstr(strTemp.c_str(), wtrSectionName); strSectionName.push_back(wtrSectionName); } } } } // long CIniFile::GetLongValueA(const string& strSectionName, const string& strKeyName) { string strValue =GetStringValueA(strSectionName, strKeyName); if(strValue !="") { return atol(strValue.c_str()); } else return 0; } double CIniFile::GetDoubleValueA(const string& strSectionName, const string& strKeyName) { string strValue =GetStringValueA(strSectionName, strKeyName); if(strValue !="") { return atof(strValue.c_str()); } else return 0; } string CIniFile::GetStringValueA(const string& strSectionName, const string& strKeyName) { IniMap::iterator pos; KeyMap::iterator poskey; for (pos = m_IniMap.begin();pos != m_IniMap.end(); ++pos) { if ((pos->first).strName == strSectionName)//找到节 { for (poskey = pos->second.begin(); poskey != pos->second.end(); ++poskey) { if ((poskey->first).strName == strKeyName)//找到键 { return poskey->second;//返回键值 } } } } return ""; } long CIniFile::GetLongValueW(const wstring& wtrSectionName, const wstring& wtrKeyName) { string strSectionName, strKeyName; wstr2astr(wtrSectionName.c_str(),strSectionName); wstr2astr(wtrKeyName.c_str(),strKeyName); return GetLongValueA(strSectionName, strKeyName); } double CIniFile::GetDoubleValueW(const wstring& wtrSectionName, const wstring& wtrKeyName) { string strSectionName, strKeyName; wstr2astr(wtrSectionName.c_str(),strSectionName); wstr2astr(wtrKeyName.c_str(),strKeyName); return GetDoubleValueA(strSectionName, strKeyName); } wstring CIniFile::GetStringValueW(const wstring& wtrSectionName, const wstring& wtrKeyName) { string strSectionName, strKeyName, strValue; wstr2astr(wtrSectionName.c_str(), strSectionName); wstr2astr(wtrKeyName.c_str(), strKeyName); strValue = GetStringValueA(strSectionName, strKeyName); wstring wtrValue; astr2wstr(strValue.c_str(), wtrValue); return wtrValue; } // bool CIniFile::SetLongValueA(const string& strSectionName, const string& strKeyName, long lValue) { string strValue = to_string<long>(lValue,std::dec); return SetStringValueA(strSectionName, strKeyName, strValue) != 0; } bool CIniFile::SetDoubleValueA(const string& strSectionName, const string& strKeyName, double fValue) { char szbuf[32]; sprintf(szbuf,"%.4f",fValue);//精度控制转换为4位 string strValue = szbuf; return SetStringValueA(strSectionName, strKeyName, strValue) != 0; } bool CIniFile::SetStringValueA(const string& strSectionName, const string& strKeyName, const string& strValue) { if (strSectionName.length()!=0) { IniMap::iterator pos; IniMap::reverse_iterator rpos; KeyMap::iterator poskey; KeyMap::reverse_iterator rposkey; for (pos = m_IniMap.begin();pos != m_IniMap.end(); ++pos) { if ((pos->first).strName == strSectionName)//找到节名 { for (poskey = pos->second.begin(); poskey != pos->second.end(); ++poskey) { if ((poskey->first).strName == strKeyName)//找到该键名 { ((poskey->second) = strValue);//重新设值 return true; } } if (poskey == (pos->second.end()))//节下无该键名 { for (rposkey = pos->second.rbegin();rposkey != pos->second.rend();++rposkey)//该键名不存在则添加 { KeyNode temp_key_node; KeyMap& key_map = pos->second; temp_key_node.strName = strKeyName; temp_key_node.lIndex = rposkey->first.lIndex +1; key_map[temp_key_node] = strValue; return true; } } } } if (pos == m_IniMap.end())//该节名不存在 { for (rpos = m_IniMap.rbegin(); rpos != m_IniMap.rend(); ++rpos) { SectionNode temp_section_node; KeyNode temp_key_node; KeyMap key_map; temp_key_node.lIndex += 1; temp_key_node.strName = strKeyName; temp_section_node.lIndex = rpos->first.lIndex + 1; temp_section_node.strName = strSectionName; key_map[temp_key_node] = strValue; m_IniMap[temp_section_node] = key_map; return true; } } if (m_IniMap.empty()) { SectionNode temp_section_node; KeyNode temp_key_node; KeyMap key_map; temp_key_node.lIndex += 1; temp_key_node.strName = strKeyName; temp_section_node.lIndex += 1; temp_section_node.strName = strSectionName; key_map[temp_key_node] = strValue; m_IniMap[temp_section_node] = key_map; return true; } } return false; } bool CIniFile::SetLongValueW(const wstring& wtrSectionName, const wstring& wtrKeyName, long lngValue) { string strSectionName, strKeyName; wstr2astr(wtrSectionName.c_str(), strSectionName); wstr2astr(wtrKeyName.c_str(), strKeyName); return SetLongValueA(strSectionName, strKeyName, lngValue); } bool CIniFile::SetDoubleValueW(const wstring& wtrSectionName, const wstring& wtrKeyName, double fValue) { string strSectionName, strKeyName; wstr2astr(wtrSectionName.c_str(), strSectionName); wstr2astr(wtrKeyName.c_str(), strKeyName); return SetDoubleValueA(strSectionName, strKeyName, fValue); } bool CIniFile::SetStringValueW(const wstring& wtrSectionName, const wstring& wtrKeyName, const wstring& wtrValue) { string strSectionName, strKeyName, strValue; wstr2astr(wtrSectionName.c_str(), strSectionName); wstr2astr(wtrKeyName.c_str(), strKeyName); wstr2astr(wtrValue.c_str(), strValue); return SetStringValueA(strSectionName, strKeyName,strValue); } // bool CIniFile::AddSectionA(const string& strSectionName) { if (strSectionName.length()!=0) { IniMap::iterator pos; IniMap::reverse_iterator rpos; SectionNode temp_section_node; for (pos = m_IniMap.begin(); pos != m_IniMap.end(); ++pos) { if (pos->first.strName == strSectionName)// 该节已经存在 { return true; } } if (pos == m_IniMap.end()) { for (rpos = m_IniMap.rbegin(); rpos != m_IniMap.rend(); ++rpos) { temp_section_node.lIndex = rpos->first.lIndex + 1; temp_section_node.strName = strSectionName; m_IniMap[temp_section_node]; return true; } } if (m_IniMap.empty()) { temp_section_node.lIndex += 1; temp_section_node.strName = strSectionName; m_IniMap[temp_section_node]; return true; } } return false; } bool CIniFile::DeleteSectionA(const string& strSectionName) { IniMap::iterator pos; SectionNode tempSectionNode; for (pos = m_IniMap.begin(); pos != m_IniMap.end();) { if (pos->first.strName == strSectionName) { pos = m_IniMap.erase(pos); return true; } else { ++pos; } } return false; } bool CIniFile::AddKeyA(const string& strSectionName, const string& strKeyName) { if (strSectionName.length()!=0) { IniMap::iterator pos; IniMap::reverse_iterator rpos; KeyMap::iterator poskey; KeyMap::reverse_iterator rposkey; for (pos = m_IniMap.begin(); pos != m_IniMap.end(); ++pos) { if (pos->first.strName == strSectionName)//节存在 { for (poskey = pos->second.begin(); poskey != pos->second.end(); ++poskey) { if (poskey->first.strName == strKeyName)//键已经存在 { return true; } } if (poskey == pos->second.end())//键不存在 { for (rposkey = pos->second.rbegin(); rposkey != pos->second.rend(); ++rposkey) { KeyNode temp_key_node; KeyMap& key_map = pos->second; temp_key_node.lIndex = rposkey->first.lIndex + 1; temp_key_node.strName = strKeyName; key_map[temp_key_node]; return true; } } } } if (pos == m_IniMap.end() || m_IniMap.empty()) { string strTempValue; SetStringValueA(strSectionName, strKeyName,strTempValue); return true; } } return false; } bool CIniFile::DeleteKeyA(const string& strSectionName, const string& strKeyName)//删除函数实现失败 { IniMap::iterator pos; KeyMap::iterator poskey; // m_IniMap.erase(Itr_pos)在迭代期间是不能被删除的,因为删除迭代器所指的对象会影响迭代本身的进行 for (pos = m_IniMap.begin();pos != m_IniMap.end(); ++pos) { if ((pos->first).strName == strSectionName) { break; } } if (pos == m_IniMap.end()) return false; KeyMap& key_map = pos->second;// for (poskey = key_map.begin();poskey != key_map.end();) { if ((poskey->first).strName == strKeyName) { poskey = key_map.erase(poskey); return true; } else { ++poskey; } } return false; } bool CIniFile::AddKeyW(const wstring& wtrSectionName, const wstring& wtrKeyName) { string strSectionName, strKeyName; wstr2astr(wtrSectionName.c_str(), strSectionName); wstr2astr(wtrKeyName.c_str(), strKeyName); return AddKeyA(strSectionName, strKeyName); } bool CIniFile::DeleteKeyW(const wstring& wtrSectionName, const wstring& wtrKeyName) { string strSectionName, strKeyName; wstr2astr(wtrSectionName.c_str(), strSectionName); wstr2astr(wtrKeyName.c_str(), strKeyName); return DeleteKeyA(strSectionName, strKeyName); } bool CIniFile::AddSectionW(const wstring& wtrSectionName) { string strSectionName; wstr2astr(wtrSectionName.c_str(),strSectionName); return AddSectionA(strSectionName); } bool CIniFile::DeleteSectionW(const wstring& wtrSectionName) { string strSectionName; wstr2astr(wtrSectionName.c_str(), strSectionName); return DeleteSectionA(strSectionName); } // bool CIniFile::SaveAs(LPCTSTR lpFileName, int/*enFileType*/ emFileType) { if (!m_IniMap.empty())//当m_IniMap中无数据时不写 { m_hIniFile = CreateFile(lpFileName,GENERIC_WRITE, 0, NULL, CREATE_ALWAYS/*TRUNCATE_EXISTING*/, FILE_ATTRIBUTE_NORMAL, NULL);//打开一个文件并将文件清空 if (m_hIniFile == INVALID_HANDLE_VALUE) { return false; } IniMap::iterator pos; KeyMap::iterator poskey; bool bWriteResult = false; DWORD dwWritten = 0; if (emFileType == Type_Lit_UNICODE||emFileType==Type_big_UNICODE)//文件为Unicode时写入 { char wbuf[2]={0xFF,0xFE}; if ((is_big_endian() ^ (Type_big_UNICODE==emFileType))) { char* pH = (char*)wbuf; char* pL = (char*)(pH+1); swap(*pH,*pL); } wstring WstrSection, WstrKeyValue; string strSection, strKeyValue; bWriteResult = WriteFile(m_hIniFile, wbuf, 2, &dwWritten, NULL); //写入前缀 if (bWriteResult == false&&dwWritten==0) { return false; } for (pos = m_IniMap.begin(); pos != m_IniMap.end(); ++pos) { if ((pos->first).endofline==CR_and_LF) { strSection ="[" + (pos->first).strName + "]\r\n"; } else if ((pos->first).endofline==Only_CR) { strSection ="[" + (pos->first).strName + "]\r"; } else { strSection ="[" + (pos->first).strName + "]\n"; } astr2wstr(strSection.c_str(), WstrSection); if ((is_big_endian() ^ (Type_big_UNICODE==emFileType))) { for (const wchar_t* pwc = WstrSection.c_str(); *pwc != L'\0';++pwc)//交换字符值的编码 { char* pH = (char*)pwc; char* pL = (char*)(pH+1); swap(*pH,*pL); } } bWriteResult = WriteFile(m_hIniFile, WstrSection.c_str(), sizeof(wchar_t)*WstrSection.length(), &dwWritten, NULL); if (bWriteResult == false&&dwWritten == 0) { return false; } for (poskey = pos->second.begin(); poskey != pos->second.end(); ++poskey) { if ((poskey->first).endofline==CR_and_LF) { strKeyValue = (poskey->first).strName + "=" + (poskey->second)+"\r\n"; } else if ((poskey->first).endofline==Only_CR) { strKeyValue = (poskey->first).strName + "=" + (poskey->second)+"\r"; } else { strKeyValue = (poskey->first).strName + "=" + (poskey->second)+"\n"; } astr2wstr(strKeyValue.c_str(), WstrKeyValue); if ((is_big_endian() ^ (Type_big_UNICODE==emFileType))) { for (const wchar_t* pwc = WstrKeyValue.c_str(); *pwc != L'\0';++pwc) { char* pH = (char*)pwc; char* pL = (char*)(pH+1); swap(*pH,*pL); } } WriteFile(m_hIniFile, WstrKeyValue.c_str(), sizeof(wchar_t)*WstrKeyValue.length(), &dwWritten, NULL); } } } else if(emFileType==Type_ANSI)//当文件原有格式为ANSI、空文件或不存在时,写入ANSI格式文本 { string strSection, strKeyValue; for (pos = m_IniMap.begin(); pos != m_IniMap.end(); ++pos) { if ((pos->first).endofline==CR_and_LF) { strSection = "[" + (pos->first).strName + "]\r\n"; } else if ((pos->first).endofline==Only_CR) { strSection = "[" + (pos->first).strName + "]\r"; } else { strSection = "[" + (pos->first).strName + "]\n"; } bWriteResult = WriteFile(m_hIniFile, strSection.c_str(), sizeof(char)*strSection.length(), &dwWritten, NULL); if (bWriteResult == false&&dwWritten == 0) { return false; } for (poskey = pos->second.begin(); poskey != pos->second.end(); ++poskey) { if ((poskey->first).endofline==CR_and_LF) { strKeyValue = (poskey->first).strName + "=" + (poskey->second) + "\r\n"; } else if ((poskey->first).endofline==Only_CR) { strKeyValue = (poskey->first).strName + "=" + (poskey->second) + "\r"; } else { strKeyValue = (poskey->first).strName + "=" + (poskey->second) + "\n"; } WriteFile(m_hIniFile, strKeyValue.c_str(), sizeof(char)*strKeyValue.length(), &dwWritten, NULL); } } } } CloseHandle(m_hIniFile); return true; } bool CIniFile::Save()//保存修改到当前文件中 { if(m_lpFilePath==NULL) return false; assert(m_FileType != Type_INVALID); return SaveAs(m_lpFilePath, m_FileType); } void CIniFile::Printf(bool bDosOrWin32)//Test Fuction { IniMap::iterator pos; KeyMap::iterator poskey; if(bDosOrWin32)//在Dos下输出测试 { for (pos = m_IniMap.begin(); pos != m_IniMap.end(); ++pos) { cout<<"["<<pos->first.strName<<"]"<<endl; for (poskey = pos->second.begin(); poskey != pos->second.end(); ++poskey) { cout<<poskey->first.strName<<"="<<poskey->second<<endl; } } } else { for (pos = m_IniMap.begin(); pos != m_IniMap.end(); ++pos) { string strSectionName = "["+(pos->first).strName+"]"+"\r\n"; OutputDebugStringA(strSectionName.c_str()); for (poskey = pos->second.begin(); poskey != pos->second.end(); ++poskey) { string strKeyName = (poskey->first).strName; string strValue = (poskey->second)+"\r\n"; OutputDebugStringA(strKeyName.c_str()); OutputDebugStringA("="); OutputDebugStringA(strValue.c_str()); } } } } // CIniFile.cpp : 定义控制台应用程序的入口点。 // #include <iostream> #include "IniFile.h" void main(void) { CIniFile myfile; myfile.Open(_T("D:\\project\\inifile\\Test.ini")); myfile.Printf(true); //myfile.Printf(true); /* #ifdef UNICODE wstring strvalue; vector<wstring> strSectionName; #else string strvalue; vector<string> strSectionName; #endif myfile.AddSection(_T("grikj")); myfile.DeleteKey(_T("CopyFiles.64"), _T("stlang64.dll")); myfile.DeleteSection(_T("APPS")); myfile.SetStringValue(_T("bank"),_T("worhle"),_T("good")); myfile.SetDoubleValue(_T("Hyello"), _T("account"), 10003.838); myfile.AddKey(_T("lee"),_T("soin")); myfile.Save(); strvalue = myfile.GetStringValue(_T("ICON"), _T("ICON_NET_NOT_LOGIN")); myfile.SaveAs(_T("D:\\Projects\\DosIniFile\\Test.ini"),0); myfile.Save(); myfile.Printf(false); */ myfile.Save(); system("pause"); }