读写ini文件

本文采用两种方法实现读写ini文件,第一种方法是自己封装的类,实现读写ini ,第二种方法是采用API函数,实现读写ini 文件;

方法一:

.ini文件是项目配置文件,本功能完成读取和写入.ini文件,其实现过程完成读字符串、写字符串、读二进制、写二进制、读整数、写整数、读double、写double八个函数;在函数实现过程中分别调用Readini()Writeini()两个函数来完成读写过程,Readini()、Writeini()是封装在CIniFile类里的读写函数。

tstdlibs.h

#ifndef _TSTDLIBS_H
#define _TSTDLIBS_H


#include <string>
#include <sstream>
#include <iostream>
#include <fstream>
#include <stdlib.h>

#ifdef _WIN32
#include <tchar.h> // For _T() macro!
#else // Non Windows Platform!
#ifdef _UNICODE
typedef wchar_t TCHAR;
#ifndef _T
#define _T(s) L##s
#endif
#ifndef _TSTR
#define _TSTR(s) L##s
#endif
#else
typedef wchar_t TCHAR;
#ifndef _T
#define _T(s) s
#endif
#ifndef _TSTR
#define _TSTR(s) s

#endif
#endif
#endif


namespace tstd
{
#ifdef _UNICODE
//typedef std::wstringtstring;
typedef std::wostreamtostream;
typedef std::wistreamtistream;
typedef std::wiostreamtiostream;
typedef std::wistringstreamtistringstream;
typedef std::wostringstreamtostringstream;
typedef std::wstringstreamtstringstream;
typedef std::wifstreamtifstream;
typedef std::wofstreamtofstream;
typedef std::wfstreamtfstream;
typedef std::wfilebuftfilebuf;
typedef std::wios tios;
typedef std::wstreambuftstreambuf;
typedef std::wstreampoststreampos;
typedef std::wstringbuftstringbuf;


// declare an unnamed namespace as a superior alternative to the use of global static variable declarations.
namespace
{
tostream& tcout = std::wcout;
tostream& tcerr = std::wcerr;
tostream& tclog = std::wclog;
tistream& tcin= std::wcin;


std::wostream& tendl( std::wostream& output )
{
output << std::endl;
return output;
}


tstring wstr_to_tstr(const std::wstring& arg)
{
return arg;
}


tstring str_to_tstr(const std::string& arg)
{
tstring res(arg.length(), L'\0');
mbstowcs_s(NULL,const_cast<wchar_t*>(res.data()),MAX_PATH ,arg.c_str(),arg.length());
return res;
}


std::wstring tstr_to_wstr(const tstring& arg)
{
return arg;
}


std::string tstr_to_str(const tstring& arg)
{
std::string res(arg.length(), '\0');
wcstombs_s(NULL,const_cast<char*>(res.data()),MAX_PATH,arg.c_str(), arg.length());
return res;
}
}


#else


//typedef std::string tstring;
typedef std::ostreamtostream;
typedef std::istreamtistream;
typedef std::iostreamtiostream;
typedef std::istringstreamtistringstream;
typedef std::ostringstreamtostringstream;
typedef std::stringstreamtstringstream;
typedef std::ifstreamtifstream;
typedef std::ofstreamtofstream;
typedef std::fstreamtfstream;
typedef std::filebuftfilebuf;
typedef std::iostios;
typedef std::streambuftstreambuf;
typedef std::streampoststreampos;
typedef std::stringbuftstringbuf;


// declare an unnamed namespace as a superior alternative to the use of global static variable declarations.
namespace
{
tostream& tcout = std::cout;
tostream& tcerr = std::cerr;
tostream& tclog = std::clog;
tistream& tcin= std::cin;


std::ostream& tendl( std::ostream& output )
{
output << std::endl;
return output;
}


tstring wstr_to_tstr(const std::wstring& arg)
{
tstring res( arg.length(), '\0' );
wcstombs( const_cast<char*>(res.data()) , arg.c_str(), arg.length());
return res;
}


tstring str_to_tstr(const std::string& arg)
{
return arg;
}


std::wstring tstr_to_wstr(const tstring& arg)
{
std::wstring res(arg.length(), L'\0');
mbstowcs(const_cast<wchar_t*>(res.data()), arg.c_str(), arg.length());
return res;
}


std::string tstr_to_str(const tstring& arg)
{
return arg;
}
}


#endif
}

#endif

inifile.h

//读写ini
//*******************************************************************************************************************************


#ifndef __CINIFILE_H_
#define __CINIFILE_H_

#include <set>
#include <algorithm>
#include <fstream>

#ifdef _UNICODE
typedef std::wfstream tfstream;
typedef std::wifstream tifstream;
typedef std::wofstream tofstream;
#else
typedef std::fstream tfstream;
typedef std::ifstream tifstream;
typedef std::ofstream tofstream;
#endif


class CIniFile;
class CFileName;


class CSaveFileName
{
friend class CFileName;
private:
CSaveFileName( CFileName* pFileName , const tstring& sFileName );
~CSaveFileName();
public:
CFileName* m_pFileName;
tstring m_sFileName;
public:
CIniFile* m_pIniFile;
};
struct cfn_less_w
{
bool operator() (const CSaveFileName* s1, const CSaveFileName* s2) const
{
#ifndef _WIN32
return wcscasecmp(s1->m_sFileName.c_str(), s2->m_sFileName.c_str()) < 0;
#else
return _wcsicmp(s1->m_sFileName.c_str(), s2->m_sFileName.c_str()) < 0;
#endif
}
};
typedef std::set<CSaveFileName*,cfn_less_w> FileIndex;


class CFileName
{
public:
CFileName();
~CFileName();


public:
CSaveFileName* GetFileName( tstring sFileName );

private:
FileIndex::const_iterator _find_file( const tstring& sFileName ) const;
FileIndex::iterator _find_file( const tstring& sFileName );
void RemoveAllFileNames();
FileIndex m_FileNames;
};


class CIniKey
{
friend class CIniSection; // Allow CIniSectionW to create keys
private: // CIniFileW acts as a class factory for CIniSectionW Objects
CIniKey( CIniSection* pSection , const tstring& sKeyName );
CIniKey( const CIniKey& ); // No Copy
CIniKey& operator=(const CIniKey&); // No Copy
~CIniKey( );
public:
// Sets the value of the key
void SetValue( const tstring& sValue );
// Returns the value of the key
std::wstring GetValue() const;
// Sets the key name, returns true on success, fails if the section
// name sKeyName already exists
bool SetKeyName( tstring sKeyName );
// Returns the name of the Key
tstring GetKeyName() const;
public:
// Pointer to the parent CIniSectionW
CIniSection* m_pSection;
// Name of the Key
tstring m_sKeyName;
// Value associated
tstring m_sValue;
}; // End of CIniKeyW


// Typedef of set of CIniKeyW pointers
struct ckey_less_w
{
bool operator() (const CIniKey* s1, const CIniKey* s2) const
{
#ifndef _WIN32
return wcscasecmp(s1->m_sKeyName.c_str(), s2->m_sKeyName.c_str()) < 0;
#else
return _wcsicmp(s1->m_sKeyName.c_str(), s2->m_sKeyName.c_str()) < 0;
#endif
}
};
//将CIniKeyW按照ci_less_a排序准则进行排序,排序后的数据存储在set
typedef std::set<CIniKey*,ckey_less_w> KeyIndex;


class CIniSection
{
friend class CIniFile; // Allow CIniFileW to create sections
public:


private: // CIniSectionW acts as a class factory for CIniKeyW Objects
CIniSection( CIniFile* pIniFile , const tstring& sSectionName );
CIniSection( const CIniSection& ); // No Copy
CIniSection& operator=(const CIniSection&); // No Copy
~CIniSection( );
public:
// Adds a key to the CIniSectionW object, returns a CIniKeyW pointer to the new or existing object
CIniKey* AddKey( tstring sKeyName );
// Removes a single key by pointer
void RemoveKey( CIniKey* pKey );
// Removes a single key by string
void RemoveKey( tstring sKey );
// Removes all the keys in the section
void RemoveAllKeys( );
// Returns a CIniKeyW pointer to the key by name, NULL if it was not found
CIniKey* GetKey( tstring sKeyName ) const;
// Returns all keys in the section by KeyIndex only to be used for enumeration
const KeyIndex& GetKeys() const;
// Returns a KeyValue at a certain section
tstring GetKeyValue( tstring sKey ) const;
// Sets a KeyValuePair at a certain section
void SetKeyValue( tstring sKey, const tstring& sValue );
// Sets the section name, returns true on success, fails if the section
// name sSectionName already exists
bool SetSectionName( tstring sSectionName );
// Returns the section name
tstring GetSectionName() const;
public:
KeyIndex::const_iterator _find_key( const tstring& sKeyName ) const;
KeyIndex::iterator _find_key( const tstring& sKeyName );
public:
// CIniFileW pointer back to the object that instanciated the section
CIniFile* m_pIniFile;
// Name of the section
tstring m_sSectionName;
// List of CIniKeyW pointers ( Keys in the section )
KeyIndex m_keys;
}; // End of CIniSectionW


// Typedef of a List of CIniSectionW pointers
struct csec_less_w
{
bool operator() (const CIniSection* s1, const CIniSection* s2) const //
{
#ifndef _WIN32
return wcscasecmp(s1->m_sSectionName.c_str(), s2->m_sSectionName.c_str()) < 0;
#else
return _wcsicmp(s1->m_sSectionName.c_str(), s2->m_sSectionName.c_str()) < 0;
#endif
}
};


typedef std::set<CIniSection*,csec_less_w> SecIndex;
//将CIniSectionW按照ci_less_a排序准则进行排序,排序后的数据存储在set


class CIniFile
{
public:
tfstream m_input;
static const wchar_t* const LF;
public:
CIniFile(const tstring& fileName);
~CIniFile();


// Save data to an output stream
void Save();
// Load data from an input stream
void Load(bool bMerge = false );


//写ini文件
bool CIniFile::Writeini (LPCTSTR sSection,LPCTSTR sKeyName,LPCTSTR sValue ,LPCTSTR fileName);
//读ini文件
tstring CIniFile::Readini(LPCTSTR sSection,LPCTSTR sKeyName, LPWSTR sValue , LPCTSTR lpszDefaultValue,LPCTSTR fileName,size_t cchValueMax);


public:
// Adds a section to the CIniFileW object, returns a CIniFileW pointer to the new or existing object
CIniSection* AddSection( tstring sSection );
// Removes section by pointer
void RemoveSection( CIniSection* pSection );
// Removes a section by its name sSection
void RemoveSection( tstring sSection );
// Removes all existing sections
void RemoveAllSections( );
// Returns a CIniSectionW* to the section by name, NULL if it was not found
CIniSection* GetSection( tstring sSection ) const;
// Returns all sections in the inifile by SecIndex, only to be used for enumeration (DO NOT KEEP THE REF OR TRY TO DELETE STUFF!)
const SecIndex& GetSections() const;
// Returns a KeyValue at a certain section
tstring GetKeyValue( const tstring& sSection, const tstring& sKey ) const;
// Sets a KeyValuePair at a certain section
void SetKeyValue( const tstring& sSection, const tstring& sKey, const tstring& sValue );
// Renames an existing section returns true on success, false if the section didn't exist or there was another section with the same sNewSectionName
bool RenameSection( const tstring& sSectionName , const tstring& sNewSectionName );
// Renames an existing key returns true on success, false if the key didn't exist or there was another section with the same sNewSectionName
bool RenameKey( const tstring& sSectionName , const tstring& sKeyName , const tstring& sNewKeyName);
CFileName* PFileName;
public:
SecIndex::const_iterator _find_sec( const tstring& sSection ) const;
SecIndex::iterator _find_sec( const tstring& sSection );
private:
CIniFile( const CIniFile&); // No Copy
CIniFile& operator=(const CIniFile&); // No Copy
public:
// List of CIniSectionW pointers ( List of sections in the class )
SecIndex m_sections;
tstring m_strFileName;
}; // End of CIniFileW

#endif

Profile.h



#pragma once
#include "inifile.h"
#include "CoreMain.h"


class CProfile
{
public:
CProfile(void);
~CProfile(void);
VOID Init();
VOID UnInit();
INT ReadProfileString(__in LPCTSTR lpszIniFileName, __in_opt LPCTSTR lpszSection, __in LPCTSTR lpszKey, __out_ecount(cchValueMax) LPTSTR lpszValue, __in size_t cchValueMax, __in_opt LPTSTR lpszDefaultValue);
SSN_RETURN WriteProfileString(__in LPCTSTR lpszIniFileName, __in_opt LPCTSTR lpszSection, __in LPCTSTR lpszKey, __in LPCTSTR lpszValue);


INT ReadProfileBinary(__in LPCTSTR lpszIniFileName, __in_opt LPCTSTR lpszSection, __in LPCTSTR lpszKey, __inout BYTE* pData, __in UINT nBytes);
SSN_RETURN WriteProfileBinary(__in LPCTSTR lpszIniFileName, __in_opt LPCTSTR lpszSection, __in LPCTSTR lpszKey, __in BYTE* pData, __in UINT nBytes);


INT ReadProfileInt(__in LPCTSTR lpszIniFileName, __in_opt LPCTSTR lpszSection, __in LPCTSTR lpszKey, __in_opt INT nDefault);
SSN_RETURN WriteProfileInt(__in LPCTSTR lpszIniFileName, __in_opt LPCTSTR lpszSection, __in LPCTSTR lpszKey, __in INT nValue);


DOUBLE ReadProfileDouble(__in LPCTSTR lpszIniFileName, __in_opt LPCTSTR lpszSection, __in LPCTSTR lpszKey, __in_opt DOUBLE dDefault);
SSN_RETURN WriteProfileDouble(__in LPCTSTR lpszIniFileName, __in_opt LPCTSTR lpszSection, __in LPCTSTR lpszKey, __in DOUBLE dValue);
CFileName m_FileName;

};

inifile.cpp

#include "StdAfx.h"
#include "inifile.h"
#include <algorithm>
#include <iostream>
#include <fstream>




#ifdef _WIN32 // Windows default is \r\n
#ifdef _FORCE_UNIX_LINEFEED
#define _CRLFA "\n"
#define _CRLFW L"\n"
#else
#define _CRLFA "\r\n"
#define _CRLFW L"\r\n"
#endif


#else // Standard format is \n for unix
#ifdef _FORCE_WINDOWS_LINEFEED
#define _CRLFA "\r\n"
#define _CRLFW L"\r\n"
#else
#define _CRLFA "\n"
#define _CRLFW L"\n"
#endif
#endif


// Convert wstring to string
std::string wstr_to_str(const std::wstring& arg)
{
std::string res( arg.length(), '\0' );
wcstombs_s(NULL,const_cast<char*>(res.data()),MAX_PATH,arg.c_str(), arg.length());
return res;
}


// Convert string to wstring
std::wstring str_to_wstr(const std::string& arg)
{
std::wstring res(arg.length(), L'\0');
mbstowcs_s(NULL,const_cast<wchar_t*>(res.data()),MAX_PATH ,arg.c_str(),arg.length());
return res;
}





void RTrim(tstring &str, const tstring& chars = _T(" \t"))
{
str.erase(str.find_last_not_of(chars)+1);
}


void LTrim(tstring &str, const tstring& chars =_T(" \t" ))
{
str.erase(0, str.find_first_not_of(chars));
}


void Trim( tstring& str , const tstring& chars =_T(" \t" ))
{
str.erase(str.find_last_not_of(chars)+1);
str.erase(0, str.find_first_not_of(chars));
}


CIniFile::CIniFile(const tstring& fileName)
{
m_strFileName = fileName;
Load(false);
}


CIniFile::~CIniFile()
{
Save();
RemoveAllSections( );
}


const wchar_t* const CIniFile::LF = _CRLFW;


void CIniFile::Save()
{
tstring sSection;
if (m_strFileName.empty())
{
assert(FALSE);
return;
}
tofstream output;
output.open(m_strFileName);
for( SecIndex::iterator itr = m_sections.begin() ; itr != m_sections.end() ; ++itr )
{
sSection = L"[" + (*itr)->GetSectionName() + L"]";


output << sSection << _CRLFA;


for( KeyIndex::iterator klitr = (*itr)->m_keys.begin() ; klitr != (*itr)->m_keys.end() ; ++klitr )
{
std::wstring sKey = (*klitr)->GetKeyName() + L"=" + (*klitr)->GetValue();
output << sKey << _CRLFA;
}
}
output.close();
}


void CIniFile::Load(bool bMerge )
{
if( !bMerge )
RemoveAllSections();
if (m_strFileName.empty())
{
assert(FALSE);
return;
}
tfstream input;
input.open(m_strFileName, std::ios::in|std::ios::app);
CIniSection* pSection = NULL;
tstring sRead;
enum { KEY , SECTION , COMMENT , OTHER };


while( std::getline( input , sRead ) )
{


// Trim all whitespace on the left
LTrim( sRead );
// Trim any returns
RTrim( sRead ,_T("\n\r"));


if( !sRead.empty() )
{
unsigned int nType = ( sRead.find_first_of(L"[") == 0 && ( sRead[sRead.find_last_not_of(L" \t\r\n")] == L']' ) ) ? SECTION : OTHER ;
nType = ( (nType == OTHER) && ( sRead.find_first_of(L"=") != tstring::npos && sRead.find_first_of(L"=") > 0 ) ) ? KEY : nType ;
nType = ( (nType == OTHER) && ( sRead.find_first_of(L"#") == 0) ) ? COMMENT : nType ;


switch( nType )
{
case SECTION:
pSection = AddSection( sRead.substr( 1 , sRead.size() - 2 ) );
break;


case KEY:
{
// Check to ensure valid section... or drop the keys listed
if( pSection )
{
size_t iFind = sRead.find_first_of(L"=");
tstring sKey = sRead.substr(0,iFind);
tstring sValue = sRead.substr(iFind + 1);
CIniKey* pKey = pSection->AddKey( sKey );
if( pKey )
{
pKey->SetValue( sValue );
}
}
}
break;
case COMMENT:
break;
case OTHER:
break;
}
}
}
input.close();
}




const SecIndex& CIniFile::GetSections() const
{
return m_sections;
}


CIniSection* CIniFile::GetSection( tstring sSection ) const
{
Trim(sSection);
SecIndex::const_iterator itr = _find_sec( sSection );
if( itr != m_sections.end() )
return *itr;
return NULL;
}


CIniSection* CIniFile::AddSection( tstring sSection )
{
Trim(sSection);
SecIndex::const_iterator itr = _find_sec( sSection );
if( itr == m_sections.end() )
{
// Note constuctor doesn't trim the string so it is trimmed above
CIniSection* pSection = new CIniSection( this , sSection );
m_sections.insert(pSection);
return pSection;
}
else
return *itr;
}




tstring CIniFile::GetKeyValue( const tstring& sSection, const tstring& sKey ) const
{
tstring sValue;
CIniSection* pSec = GetSection( sSection );
if( pSec )
{
CIniKey* pKey = pSec->GetKey( sKey );
if( pKey )
sValue = pKey->GetValue();
}
return sValue;
}


void CIniFile::SetKeyValue( const tstring& sSection, const tstring& sKey, const tstring& sValue )
{
CIniSection* pSec = AddSection( sSection );
if( pSec )
{
CIniKey* pKey = pSec->AddKey( sKey );
if( pKey )
pKey->SetValue( sValue );
}
}




void CIniFile::RemoveSection( std::wstring sSection )
{
Trim(sSection);
SecIndex::iterator itr = _find_sec( sSection );
if( itr != m_sections.end() )
{
delete *itr;
m_sections.erase( itr );
}
}


void CIniFile::RemoveSection( CIniSection* pSection )
{
// No trim since internal object not from user
SecIndex::iterator itr = _find_sec( pSection->m_sSectionName );
if( itr != m_sections.end() )
{
delete *itr;
m_sections.erase( itr );
}
}


void CIniFile::RemoveAllSections( )
{
for( SecIndex::iterator itr = m_sections.begin() ; itr != m_sections.end() ; ++itr )
{
delete *itr;
}
m_sections.clear();
}




bool CIniFile::RenameSection( const tstring& sSectionName , const tstring& sNewSectionName )
{
// Note string trims are done in lower calls.
bool bRval = false;
CIniSection* pSec = GetSection( sSectionName );
if( pSec )
{
bRval = pSec->SetSectionName( sNewSectionName );
}
return bRval;
}


bool CIniFile::RenameKey( const tstring& sSectionName , const tstring& sKeyName , const tstring& sNewKeyName)
{
// Note string trims are done in lower calls.
bool bRval = false;
CIniSection* pSec = GetSection( sSectionName );
if( pSec != NULL)
{
CIniKey* pKey = pSec->GetKey( sKeyName );
if( pKey != NULL )
bRval = pKey->SetKeyName( sNewKeyName );
}
return bRval;
}


// Returns a constant iterator to a section by name, string is not trimmed
SecIndex::const_iterator CIniFile::_find_sec( const tstring& sSection ) const
{
CIniSection bogus(NULL,sSection);
return m_sections.find( &bogus );
}


// Returns an iterator to a section by name, string is not trimmed
SecIndex::iterator CIniFile::_find_sec( const tstring& sSection )
{
CIniSection bogus(NULL,sSection);
return m_sections.find( &bogus );
}




//
// CIniSectionW functions start here


CIniSection::CIniSection( CIniFile* pIniFile , const tstring& sSectionName ) : m_pIniFile(pIniFile) , m_sSectionName(sSectionName)
{


}




CIniSection::~CIniSection()
{
RemoveAllKeys();
}


CIniKey* CIniSection::GetKey( tstring sKeyName ) const
{
Trim(sKeyName);
KeyIndex::const_iterator itr = _find_key( sKeyName );
if( itr != m_keys.end() )
return *itr;
return NULL;
}


void CIniSection::RemoveAllKeys()
{
for( KeyIndex::iterator itr = m_keys.begin() ; itr != m_keys.end() ; ++itr )
{
delete *itr;
}
m_keys.clear();
}


void CIniSection::RemoveKey( tstring sKey )
{
Trim( sKey );
KeyIndex::iterator itr = _find_key( sKey );
if( itr != m_keys.end() )
{
delete *itr;
m_keys.erase( itr );
}
}


void CIniSection::RemoveKey( CIniKey* pKey )
{
// No trim is done to improve efficiency since CIniKeyW* should already be trimmed
KeyIndex::iterator itr = _find_key( pKey->m_sKeyName );
if( itr != m_keys.end() )
{
delete *itr;
m_keys.erase( itr );
}
}


CIniKey* CIniSection::AddKey( tstring sKeyName )
{
Trim(sKeyName);
KeyIndex::const_iterator itr = _find_key( sKeyName );
if( itr == m_keys.end() )
{
// Note constuctor doesn't trim the string so it is trimmed above
CIniKey* pKey = new CIniKey( this , sKeyName );
m_keys.insert(pKey);
return pKey;
}
else
return *itr;
}


bool CIniSection::SetSectionName( tstring sSectionName )
{
Trim(sSectionName);
// Does this already exist.
if( m_pIniFile->_find_sec( sSectionName ) == m_pIniFile->m_sections.end() )
{
// Find the current section if one exists and remove it since we are renaming
SecIndex::iterator itr = m_pIniFile->_find_sec( m_sSectionName );


// Just to be safe make sure the old section exists
if( itr != m_pIniFile->m_sections.end() )
m_pIniFile->m_sections.erase(itr);


// Change name prior to ensure tree balance
m_sSectionName = sSectionName;


// Set the new map entry we know should not exist
m_pIniFile->m_sections.insert(this);


return true;
}
else
{
return false;
}
}


tstring CIniSection::GetSectionName() const
{
return m_sSectionName;
}


const KeyIndex& CIniSection::GetKeys() const
{
return m_keys;
}


tstring CIniSection::GetKeyValue( tstring sKey ) const
{
tstring sValue;
CIniKey* pKey = GetKey( sKey );
if( pKey )
{
sValue = pKey->GetValue();
}
return sValue;
}


void CIniSection::SetKeyValue( tstring sKey, const tstring& sValue )
{
CIniKey* pKey = AddKey( sKey );
if( pKey )
{
pKey->SetValue( sValue );
}
}


// Returns a constant iterator to a key by name, string is not trimmed
KeyIndex::const_iterator CIniSection::_find_key( const tstring& sKey ) const
{
CIniKey bogus(NULL,sKey);
return m_keys.find( &bogus );
}


// Returns an iterator to a key by name, string is not trimmed
KeyIndex::iterator CIniSection::_find_key( const tstring& sKey )
{
CIniKey bogus(NULL,sKey);
return m_keys.find( &bogus );
}


#define INI _T("Default")


bool CIniFile::Writeini (LPCTSTR sSection,LPCTSTR sKeyName,LPCTSTR sValue ,LPCTSTR fileName)
{
if((sSection==NULL)||(_tcslen(sSection)==0))
{
sSection= INI;
}
if(sKeyName==NULL||(_tcslen(sKeyName)==0))
{
return false;
}


CIniSection* pSec = AddSection( sSection );
if (pSec)
{
pSec->AddKey(sKeyName);
pSec->AddKey(sKeyName)->SetValue(sValue);
}

return true;
}


tstring CIniFile::Readini(LPCTSTR sSection,LPCTSTR sKeyName, LPTSTR sValue , LPCTSTR lpszDefaultValue,LPCTSTR fileName, size_t cchValueMax)
{
if((sSection==NULL)||(wcslen(sSection)==0))
{
sSection=INI;
}
if((sKeyName==NULL)||(wcslen(sKeyName)==0))
{
return _T("");
}
if (sValue && cchValueMax)
{
memset(sValue, 0, cchValueMax*sizeof(TCHAR));
}

tstring strValue;
//如果为空或长度为0 ,则给他一个默认值,则就不用else语句了
CIniSection* pSection = GetSection(sSection );
if( pSection )
{
CIniKey* pKey = pSection->GetKey(sKeyName);
{
if(pKey)
{
strValue = pKey->GetValue();
}
}
}


if (strValue.empty())
{
if((lpszDefaultValue!=NULL)&&(_tcslen(lpszDefaultValue)!=0))
{
strValue = lpszDefaultValue;
}
}
if (sValue && !strValue.empty())
{
_tcsncpy_s(sValue, cchValueMax, strValue.c_str(), _TRUNCATE);
}
return strValue;
}


// CIniSectionW function end here


//
// CIniKeyW Functions Start Here


CIniKey::CIniKey( CIniSection* pSection , const tstring& sKeyName ) : m_pSection(pSection) , m_sKeyName(sKeyName)
{


}




CIniKey::~CIniKey()
{


}


void CIniKey::SetValue( const tstring& sValue )
{
m_sValue = sValue;
}


tstring CIniKey::GetValue() const
{
return m_sValue;
}


bool CIniKey::SetKeyName(tstring sKeyName )
{
Trim( sKeyName );


// Check for key name conflict
if( m_pSection->_find_key( sKeyName ) == m_pSection->m_keys.end() )
{
KeyIndex::iterator itr = m_pSection->_find_key( m_sKeyName );


// Find the old map entry and remove it
if( itr != m_pSection->m_keys.end() )
m_pSection->m_keys.erase( itr );


// Change name prior to ensure tree balance
m_sKeyName = sKeyName;


// Make the new map entry
m_pSection->m_keys.insert(this);
return true;
}
else
{
return false;
}
}


std::wstring CIniKey::GetKeyName() const
{
return m_sKeyName;
}


//
//CFileName
CFileName::CFileName()
{


}


CFileName::~CFileName()
{
RemoveAllFileNames();
}


CSaveFileName* CFileName:: GetFileName( tstring sFileName )
{
Trim(sFileName);
FileIndex::const_iterator itr = _find_file( sFileName );
if( itr==m_FileNames.end() )
{
CSaveFileName* pIniFile = new CSaveFileName(this , sFileName );
m_FileNames.insert(pIniFile);
return pIniFile;
}
else
return *itr;
}


void CFileName::RemoveAllFileNames( )
{
for( FileIndex::iterator itr = m_FileNames.begin() ; itr != m_FileNames.end() ; ++itr )
{
delete *itr;
}
m_FileNames.clear();
}


FileIndex::const_iterator CFileName::_find_file( const tstring& sFileName ) const
{
CSaveFileName bogus(NULL,sFileName);
return m_FileNames.find( &bogus );
}


FileIndex::iterator CFileName::_find_file( const tstring& sFileName )
{
CSaveFileName bogus(NULL,sFileName);
return m_FileNames.find( &bogus );
}
//
//CSaveFileName
CSaveFileName::CSaveFileName( CFileName* pFileName , const tstring& sFileName ):m_pFileName(pFileName) , m_sFileName(sFileName)
{
if (pFileName && !sFileName.empty())
{
m_pIniFile = new CIniFile(sFileName);
}
else
{
m_pIniFile = NULL;
}
}


CSaveFileName::~CSaveFileName()
{
if (m_pIniFile)
{
delete m_pIniFile;
m_pIniFile = NULL;
}
}

Profile.cpp



#include "stdafx.h"
#include "CoreMain.h"
#include "Core.h"
#include "Profile.h"
#include <SSNAPI.h>




CProfile::CProfile(void)
{


}


CProfile::~CProfile(void)
{


}


VOID CProfile::Init()
{


}


VOID CProfile::UnInit()
{


}


INT CProfile::ReadProfileString(__in LPCTSTR lpszIniFileName, __in_opt LPCTSTR lpszSection, __in LPCTSTR lpszKey, __out_ecount(cchValueMax) LPTSTR lpszValue, __in size_t cchValueMax, __in_opt LPTSTR lpszDefaultValue)
{
CSaveFileName* pFileName=m_FileName.GetFileName(lpszIniFileName);
tstring reValue;
reValue = pFileName->m_pIniFile->Readini(lpszSection,lpszKey,lpszValue, lpszDefaultValue,lpszIniFileName,cchValueMax);
return reValue.length();
}


SSN_RETURN CProfile::WriteProfileString(__in LPCTSTR lpszIniFileName, __in_opt LPCTSTR lpszSection, __in LPCTSTR lpszKey, __in LPCTSTR lpszValue)
{
CSaveFileName* pFileName=m_FileName.GetFileName(lpszIniFileName);
BOOL ret =pFileName->m_pIniFile->Writeini(lpszSection,lpszKey,lpszValue,lpszIniFileName);
if(ret==TRUE)
{
return SSN_OK;
}else
{
return SSN_FALSE;
}
}


INT CProfile::ReadProfileBinary(__in LPCTSTR lpszIniFileName, __in_opt LPCTSTR lpszSection, __in LPCTSTR lpszKey, __inout BYTE* pData, __in UINT nBytes)
{
CSaveFileName* pFileName=m_FileName.GetFileName(lpszIniFileName);
TCHAR szT[MAX_PATH];
tstring reValue;
reValue = pFileName->m_pIniFile->Readini(lpszSection,lpszKey,szT, NULL,lpszIniFileName,MAX_PATH);
if (szT == NULL)
return 0;
UINT ShouldBytes =reValue.length();
if(ShouldBytes>nBytes)
{
return ShouldBytes;
}else
{
return nBytes;
}
}


SSN_RETURN CProfile::WriteProfileBinary(__in LPCTSTR lpszIniFileName, __in_opt LPCTSTR lpszSection, __in LPCTSTR lpszKey, __in BYTE* pData, __in UINT nBytes)
{
CSaveFileName* pFileName=m_FileName.GetFileName(lpszIniFileName);
LPTSTR lpsz = new TCHAR[nBytes*2+1];
UINT i;
for (i = 0; i < nBytes; i++)
{
lpsz[i*2] = (TCHAR)((pData[i] & 0x0F) + 'A'); //低字节
lpsz[i*2+1] = (TCHAR)(((pData[i] >> 4) & 0x0F) + 'A'); //高字节
}
lpsz[i*2] = 0;
BOOL ret = pFileName->m_pIniFile->Writeini(lpszSection,lpszKey,lpsz,lpszIniFileName);
if(ret==TRUE)
{
delete [] lpsz;
return SSN_OK;
}else
{
delete [] lpsz;
return SSN_FALSE;
}
}


INT CProfile::ReadProfileInt(__in LPCTSTR lpszIniFileName, __in_opt LPCTSTR lpszSection, __in LPCTSTR lpszKey, __in_opt INT nDefault)
{
CSaveFileName* pFileName=m_FileName.GetFileName(lpszIniFileName);
TCHAR szT[MAX_PATH];
TCHAR sDefault[MAX_PATH];
_stprintf_s(sDefault, _countof(szT), _T("%d"), nDefault);
tstring retValue ;
retValue =pFileName->m_pIniFile->Readini( lpszSection,lpszKey,szT,sDefault,lpszIniFileName,MAX_PATH);
INT nretValue=0;
nretValue= _ttoi(retValue.c_str());
return nretValue;
}


SSN_RETURN CProfile::WriteProfileInt( __in LPCTSTR lpszIniFileName, __in_opt LPCTSTR lpszSection, __in LPCTSTR lpszKey, __in INT nValue )
{
CSaveFileName* pFileName=m_FileName.GetFileName(lpszIniFileName);
TCHAR szT[MAX_PATH];
_stprintf_s(szT, _countof(szT), _T("%d"), nValue);
BOOL ret =pFileName->m_pIniFile->Writeini(lpszSection, lpszKey, szT,lpszIniFileName);
if(ret==TRUE)
{
return SSN_OK;
}else
{
return SSN_FALSE;
}
return SSN_FALSE;
}


DOUBLE CProfile::ReadProfileDouble( __in LPCTSTR lpszIniFileName, __in_opt LPCTSTR lpszSection, __in LPCTSTR lpszKey, __in_opt DOUBLE dDefault )
{
CSaveFileName* pFileName=m_FileName.GetFileName(lpszIniFileName);
TCHAR szT[MAX_PATH];
tstring reValue;
reValue = pFileName->m_pIniFile->Readini( lpszSection,lpszKey,szT,NULL,lpszIniFileName,MAX_PATH);
return (reValue.c_str()!= NULL) ? _tstof(reValue.c_str()) : dDefault;
}


SSN_RETURN CProfile::WriteProfileDouble( __in LPCTSTR lpszIniFileName, __in_opt LPCTSTR lpszSection, __in LPCTSTR lpszKey, __in DOUBLE dValue )
{
CSaveFileName* pFileName=m_FileName.GetFileName(lpszIniFileName);
TCHAR szT[MAX_PATH];
_stprintf_s(szT, _countof(szT), _T("%f"), dValue);
BOOL ret =pFileName->m_pIniFile->Writeini(lpszSection, lpszKey,szT,lpszIniFileName);
if (ret == TRUE )
return SSN_OK;
else
return SSN_FALSE;
}

方法二:Profile用端口API函数写的读写ini文件

#include "stdafx.h"
#define SSNAPI_EXPORTS
#include "CoreMain.h"
#include "Core.h"
#include "Profile.h"
#include <SSNAPI.h>
#include <atlstr.h>
#include <iostream>
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
using namespace std;


//
class RWini
{
public:
RWini();
~RWini();
CORE_API INT DoSsnReadProfileString( __in INT nPlugInId, __in_opt LPTSTR lpszGroupName, __in LPTSTR lpszKey, __out_ecount(cchValueMax) LPTSTR lpszValue, __in size_t cchValueMax, __in_opt LPTSTR lpszDefaultValue );
CORE_API SSN_RETURN DoSsnWriteProfileString( __in INT nPlugInId, __in_opt LPTSTR lpszGroupName, __in LPTSTR lpszKey, __in LPTSTR lpszValue );
int insert(__in INT nPlugInId, __in_opt LPTSTR lpszGroupName, __in LPTSTR lpszKey, __out_ecount(cchValueMax) LPTSTR lpszValue);
public:
INT nPlugInId[MAX_PATH];
TCHAR lGName[MAX_PATH];
TCHAR lKName[MAX_PATH];
TCHAR lpszValue[MAX_PATH];
INT nCount;
};
RWini::RWini()
{
INT nCount = 0;
}


int RWini::insert(__in INT nPlugInId, __in_opt LPTSTR lpszGroupName, __in LPTSTR lpszKey, __out_ecount(cchValueMax) LPTSTR lpszValue)
{
if (nCount<MAX_PATH)
{
nPlugInId[nCount]=nPlugInId;
lGName[nCount] =lpszGroupName; //tstring lGName = lpszGroupName;
lKName[nCount]=lpszKey;
lpszValue[nCount]=lpszValue;
nCount++;
}
}


CORE_API INT DoSsnReadProfileString( __in INT nPlugInId, __in_opt LPTSTR lpszGroupName, __in LPTSTR lpszKey, __out_ecount(cchValueMax) LPTSTR lpszValue, __in size_t cchValueMax, __in_opt LPTSTR lpszDefaultValue )
{


TCHAR szPath[MAX_PATH] = {0};
DoSsnGetPath(SSN_PATH_CONFIG, szPath, MAX_PATH, nPlugInId, NULL);
TCHAR szT[MAX_PATH];
GetPrivateProfileString(lpszGroupName, lpszKey,lpszDefaultValue, szT, cchValueMax, szPath);
//lpszGroupName 节名
//lpszKey 键名
//lpszDefaultValue 为空时的默认值
//szT 存放键值的指针变量,用于接收INI文件中键值(数据)的接收缓冲区
//cchValueMax lpReturnedString的缓冲区大小
//filename INI文件的路径
unsigned int retValueLength=_tcslen(szT);
if(cchValueMax < retValueLength)
return retValueLength;
else
return cchValueMax;
}


CORE_API SSN_RETURN DoSsnWriteProfileString( __in INT nPlugInId, __in_opt LPTSTR lpszGroupName, __in LPTSTR lpszKey, __in LPTSTR lpszValue )
{
TCHAR szPath[MAX_PATH] = {0};
DoSsnGetPath(SSN_PATH_CONFIG, szPath, MAX_PATH, nPlugInId, NULL);
//存放的路径用nPlugInId来标识,如存放文件为A_nPlugInId.ini
BOOL ret =WritePrivateProfileString(lpszGroupName,lpszKey,lpszValue,szPath);
//lpszGroupName 节名
//lpszKey 键名
//lpszValue 键值,也就是数据
//filename INI文件的路径
if(ret==TRUE){
return SSN_OK;
}else{
return SSN_FALSE;
}
}


CORE_API INT DoSsnReadProfileBinary( __in INT nPlugInId, __in_opt LPTSTR lpszGroupName, __in LPTSTR lpszKey, __out BYTE* pData, __in UINT nBytes )
{
TCHAR szPath[MAX_PATH] = {0};
DoSsnGetPath(SSN_PATH_CONFIG, szPath, MAX_PATH, nPlugInId, NULL);
TCHAR szT[MAX_PATH];
GetPrivateProfileString(lpszGroupName, lpszKey, NULL, szT, MAX_PATH, szPath);
if (szT == NULL)
return 0;
UINT ShouldBytes = _tcslen(szT);
if(ShouldBytes>nBytes){
return ShouldBytes;
}else{
return nBytes;
}
}


CORE_API SSN_RETURN DoSsnWriteProfileBinary( __in INT nPlugInId, __in_opt LPTSTR lpszGroupName, __in LPTSTR lpszKey, __in BYTE* pData, __in UINT nBytes )
{
TCHAR szPath[MAX_PATH] = {0};
DoSsnGetPath(SSN_PATH_CONFIG, szPath, MAX_PATH, nPlugInId, NULL);
// 二进制转换为字符串,并写出
LPTSTR lpsz = new TCHAR[nBytes*2+1];
UINT i;
for (i = 0; i < nBytes; i++)
{
lpsz[i*2] = (TCHAR)((pData[i] & 0x0F) + 'A'); //低字节
lpsz[i*2+1] = (TCHAR)(((pData[i] >> 4) & 0x0F) + 'A'); //高字节
}
lpsz[i*2] = 0;
BOOL ret =WritePrivateProfileString(lpszGroupName,lpszKey,lpsz,szPath);
if(ret==TRUE){
delete [] lpsz;
return SSN_OK;
}else{
delete [] lpsz;
return SSN_FALSE;
}
}


CORE_API INT DoSsnReadProfileInt( __in INT nPlugInId, __in_opt LPTSTR lpszGroupName, __in LPTSTR lpszKey, __in_opt INT nDefault )
{
TCHAR szPath[MAX_PATH] = {0};
DoSsnGetPath(SSN_PATH_CONFIG, szPath, MAX_PATH, nPlugInId, NULL);
INT retValueLength = 0;
retValueLength = GetPrivateProfileInt(lpszGroupName,lpszKey,nDefault,szPath);
//lpszGroupName 节名
//lpszKey 键名
//nDefault 如果没有找到指定的数据返回,则把个变量值赋给返回值
//nPath INI文件的路径
//读取整形值:(返回值为读到的整数)
return retValueLength;
}


CORE_API SSN_RETURN DoSsnWriteProfileInt( __in INT nPlugInId, __in_opt LPTSTR lpszGroupName, __in LPTSTR lpszKey, __in INT nValue )
{
TCHAR szPath[MAX_PATH] = {0};
DoSsnGetPath(SSN_PATH_CONFIG, szPath, MAX_PATH, nPlugInId, NULL);
TCHAR szT[MAX_PATH];
_stprintf_s(szT, _countof(szT), _T("%d"), nValue);
BOOL ret =WritePrivateProfileString(lpszGroupName, lpszKey, szT,szPath);
if(ret==TRUE){
return SSN_OK;
}else{
return SSN_FALSE;
}
}


CORE_API DOUBLE DoSsnReadProfileDouble( __in INT nPlugInId, __in_opt LPTSTR lpszGroupName, __in LPTSTR lpszKey, __in_opt DOUBLE dDefault )
{
TCHAR szPath[MAX_PATH] = {0};
DoSsnGetPath(SSN_PATH_CONFIG, szPath, MAX_PATH, nPlugInId, NULL);
TCHAR d[MAX_PATH];
GetPrivateProfileString(lpszGroupName, lpszKey, NULL, d, 128, szPath);
return (d[0] != 0) ? _wtof(d) : dDefault;
}


CORE_API SSN_RETURN DoSsnWriteProfileDouble( __in INT nPlugInId, __in_opt LPTSTR lpszGroupName, __in LPTSTR lpszKey, __in DOUBLE dValue )
{
TCHAR szPath[MAX_PATH] = {0};
DoSsnGetPath(SSN_PATH_CONFIG, szPath, MAX_PATH, nPlugInId, NULL);
char szT[MAX_PATH];
int digits=100;
_gcvt_s(szT,MAX_PATH,dValue,digits);
BOOL ret =WritePrivateProfileString(lpszGroupName,lpszKey,SSN::CA2W(szT),szPath);
//lpszGroupName 节名
//lpszKey 键名
//szT 键值,也就是数据
//nPath INI文件的路径
if (ret == TRUE )
return SSN_OK;
else
return SSN_FALSE;
}


//TODO: 还没实现,临时拷贝default


CORE_API INT DoSsnGetLocaleString( __in INT nPlugInId, __in_opt INT nLocaleId, __in_opt LPCTSTR szGroupName, __in LPCTSTR szStringId, __out_ecount(cchStringMax) LPTSTR szString, __in size_t cchStringMax, __in LPCTSTR szDefaultString )
{
TCHAR szPath[MAX_PATH] = {0};
DoSsnGetPath(SSN_PATH_LOCALE, szPath, MAX_PATH, nPlugInId, nLocaleId);
GetPrivateProfileString(szGroupName, szStringId,szDefaultString, szString, cchStringMax, szPath);
if (0 == _tcscpy_s(szString, cchStringMax, szDefaultString))
{
return _tcslen(szString);
}
else
{
return 0;
}
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
纯c读写ini配置文件 用c/c++读写ini配置文件有不少第三方的开源库,如iniparser、libini、rwini、UltraLightINIParser等,但都不理想,往往代码较大、功能较弱、 接口使用不方便。尤其在大小写处理、前后空格、各种注释、跨平台换行符支持、带引号字符串处理、无section操作、原格式保持等方面存在问题。 现将本人精心制作的ini读写程序源码奉献给大家,纯c编写,简洁好用。支持windows和linux。 主要特点: 1、支持;和#注释符号,支持行尾注释。 2、支持带引号'或"成对匹配的字符串,提取时自动去引号。引号中可带其它引号或;#注释符。 3、支持无section或空section(名称为空)。 4、支持10、16、8进制数,0x开头为16进制数,0开头为8进制。 5、支持section、key或=号前后带空格。 6、支持\n、\r、\r\n或\n\r换行格式。 7、不区分section、key大小写,但写入时以新串为准,并保持其大小写。 8、新增数据时,若section存在则在该节最后一个有效数据后添加,否则在文件尾部添加。 9、支持指定key所在整行删除,即删除该键值,包括注释。 10、可自动跳过格式错误行,修改时仍然保留。 11、修改时保留原注释:包括整行注释、行尾注释(包括前面空格)。 12、修改时保留原空行。以上三点主要是尽量保留原格式。 不足之处: 1、不支持单key多value(逗号分割),只能一次性提取后自行处理。 2、不支持同名重复section和key。(重复section可视为错误,重复key则可能造成分歧) 3、不能提取所有section或key名称。 使用只需两个文件inirw.h、inirw.c,另有测试程序和工程文件,支持windows和linux。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值