Tinifile 与 TMeminifile 对 INI 文件处理

原文链接:如有侵权请联系删除INI 文件处理, TMemIniFile, TIniFile, UTF-8, UTF-16, UNICODE - C++ Builder 编程技巧 - C++ 爱好者 (cppfans.com)http://www.cppfans.com/cbknowledge/skills/files/inifiles.asp#inifilestruct

INI 文件处理 - 文件处理
 • C++ Builder 支持的 ini 文件的结构
   · 简单的 ini 文件的结构
   · 含有 SubSections 的 ini 文件结构
 • C++ Builder 处理 ini 文件的头文件
 • 使用 TMemIniFile 处理 ini 文件,支持 UNICODE UTF-16, UTF-8
   · 指定 ini 文件的文件名和字符编码
   · AutoSave 属性和 UpdateFile() 方法
   · 读写数据
   · 删除数据
   · 读取 Sections
   · 删除 Sections
   · 整体文件的数据操作
   · TMemIniFile 的属性成员
 • 使用 TIniFile 处理 ini 文件,过时了的处理方法
 • TMemIniFile 和 TIniFile,应该使用哪一个,他们有什么区别?

C++ Builder 支持的 ini 文件的结构

简单的 ini 文件的结构

[Section1]
Indent1=Value1
Indent2=Value2

[Section2]
Indent3=Value3
Indent4=Value4

含有 SubSections 的 ini 文件结构

注1: 不要混用 “.”, “/” 和 “\” 做分割符,程序里面的写法要和文件里面的一致,
     例如 "Section1.SubSection1" 只是对应 [Section1.SubSection1] 而不对应 [Section1/SubSection1];
注2: 在 C/C++ 里面 “\” 是需要有转义符的,在程序里面不是 "Section1\SubSection1" 而是 "Section1\\SubSection1"。

用 . 分割 SubSections 的 ini 文件用 / 分割 SubSections 的 ini 文件用 \ 分割 SubSections 的 ini 文件
[Section1]
Indent1=Value1
Indent2=Value2

[Section2]
Indent3=Value3
Indent4=Value4

[Section1.SubSection1]
Indent5=Value5
Indent6=Value6
Indent7=Value7

[Section1.SubSection2]
Indent8=Value8
Indent9=Value9

[Section1.SubSection2.SubSubSec1]
IndentA=ValueA
IndentB=ValueB
IndentC=ValueC

[Section1.SubSection2.SubSubSec2]
IndentD=ValueD
IndentE=ValueE
IndentF=ValueF
[Section1]
Indent1=Value1
Indent2=Value2

[Section2]
Indent3=Value3
Indent4=Value4

[Section1/SubSection1]
Indent5=Value5
Indent6=Value6
Indent7=Value7

[Section1/SubSection2]
Indent8=Value8
Indent9=Value9

[Section1/SubSection2/SubSubSec1]
IndentA=ValueA
IndentB=ValueB
IndentC=ValueC

[Section1/SubSection2/SubSubSec2]
IndentD=ValueD
IndentE=ValueE
IndentF=ValueF
[Section1]
Indent1=Value1
Indent2=Value2

[Section2]
Indent3=Value3
Indent4=Value4

[Section1\SubSection1]
Indent5=Value5
Indent6=Value6
Indent7=Value7

[Section1\SubSection2]
Indent8=Value8
Indent9=Value9

[Section1\SubSection2\SubSubSec1]
IndentA=ValueA
IndentB=ValueB
IndentC=ValueC

[Section1\SubSection2\SubSubSec2]
IndentD=ValueD
IndentE=ValueE
IndentF=ValueF

C++ Builder 处理 ini 文件的头文件

新版本 C++ Builder 的 ini 文件处理头文件为 #include <System.IniFiles.hpp>
老版本 C++ Builder 的 ini 文件处理头文件为 #include <IniFiles.hpp> 新版本目前保留了这个头文件 (说不定再更新哪个版本就没有了)。

TMemIniFile 和 TIniFile 都在这个头文件里面。

使用 TMemIniFile 处理 ini 文件

指定 ini 文件的文件名和字符编码

TMemIniFile *ini = new TMemIniFile(L"d:\\abc.ini"); // 系统默认的文本文件字符编码 (ANSI)
 
TMemIniFile *ini = new TMemIniFile(L"d:\\abc.ini", TEncoding::UTF8); // UTF-8 编码
 
TMemIniFile *ini = new TMemIniFile(L"d:\\abc.ini", TEncoding::Unicode); // UNICODE UTF-16
 
TEncoding *encBig5 = new TMBCSEncoding(950);
TMemIniFile *ini = new TMemIniFile(L"d:\\abc.ini", encBig5); // BIG5 编码
 
TEncoding *encGBK = new TMBCSEncoding(936);
TMemIniFile *ini = new TMemIniFile(L"d:\\abc.ini", encGBK); // GBK 编码

虽然 ini 文件可以中途改文字编码,例如:
ini->Encoding = TEncoding::UTF8;
但是最好不要这样做,可能会导致乱码。
如果需要给文件转编码,可以使用 TStringList,方法请点击这里

指定的字符编码和 ini 文件本身的编码不同,打开文件会报错,例如文件是 ANSI 编码的,按照 UTF-8 读取,会报错,抛出异常。

重命名文件:Rename(新文件名, bool Reload) 的第二个参数 Reload:

ini->Rename(L"d:\\b.ini",false); // Reload=false: 重命名为 b.ini,如果有这个文件,会覆盖,没有会新创建
 
ini->Rename(L"d:\\a.ini",true); // Reload=true: 放弃原来的文件,重新加载 a.ini 文件,如果没有会新创建

AutoSave 属性和 UpdateFile() 方法

默认情况,TMemIniFile 不会自动保存 ini 文件。
 • AutoSave 属性设为 true 的情况,会在销毁 TMemIniFile 对象时存盘;默认值为 false,在销毁 TMemIniFile 对象的时候不存盘。
 • 调用 UpdateFile() 方法,会把修改的内容存盘。一般情况,在修改 ini 之后,调用 UpdateFile() 存盘。

#include <memory>
void __fastcall TForm1::Button1Click(TObject *Sender)
{
  std::auto_ptr<TMemIniFile>ini(new TMemIniFile(L"d:\\abc.ini",TEncoding::Unicode));
  ini->WriteInteger(L"OPTIONS",L"Volume",100);
  ini->WriteInteger(L"OPTIONS",L"Rate",0);
  ini->UpdateFile();
}

读写数据

下面表格是读取各种数据类型数据的方法,读取 [Section] 里面的值 Ident,如果值不存在,返回默认值 Default

读取数据的方法函数原型说明
ReadStringUnicodeString __fastcall ReadString(const UnicodeString Section, const UnicodeString Ident, const UnicodeString Default);读取字符串值
ReadIntegerint __fastcall ReadInteger(const UnicodeString Section, const UnicodeString Ident, int Default);读取整数值
ReadBoolbool __fastcall ReadBool(const UnicodeString Section, const UnicodeString Ident, bool Default);读取布尔值
ReadFloatdouble __fastcall ReadFloat(const UnicodeString Section, const UnicodeString Name, double Default);读取浮点数值
ReadDateTDateTime __fastcall ReadDate(const UnicodeString Section, const UnicodeString Name, TDateTime Default);读取日期
ReadTimeTDateTime __fastcall ReadTime(const UnicodeString Section, const UnicodeString Name, TDateTime Default);读取时间
ReadDateTimeTDateTime __fastcall ReadDateTime(const UnicodeString Section, const UnicodeString Name, TDateTime Default);读取日期和时间
ReadBinaryStreamint __fastcall ReadBinaryStream(const UnicodeString Section, const UnicodeString Name, TStream* Value);读取二进制数据

下面表格是写入数据的方法,把 Indent 的数据写入 [Section],值为 Value,如果 [Section] 或 Indent 不存在会新增,如果存在会改写。

写入数据的方法函数原型说明
WriteStringvoid __fastcall WriteString(const UnicodeString Section, const UnicodeString Ident, const UnicodeString Value);写入字符串值
WriteIntegervoid __fastcall WriteInteger(const UnicodeString Section, const UnicodeString Ident, int Value);写入整数值
WriteBoolvoid __fastcall WriteBool(const UnicodeString Section, const UnicodeString Ident, bool Value);写入布尔值
WriteFloatvoid __fastcall WriteFloat(const UnicodeString Section, const UnicodeString Name, double Value);写入浮点数
WriteDatevoid __fastcall WriteDate(const UnicodeString Section, const UnicodeString Name, TDateTime Value);写入日期
WriteTimevoid __fastcall WriteTime(const UnicodeString Section, const UnicodeString Name, TDateTime Value);写入时间
WriteDateTimevoid __fastcall WriteDateTime(const UnicodeString Section, const UnicodeString Name, TDateTime Value);写入日期和时间
WriteBinaryStreamvoid __fastcall WriteBinaryStream(const UnicodeString Section, const UnicodeString Name, TStream* Value);写入二进制数据

判断是否存在 [Section] 里面的 Indent 值

判断数据是否存在函数原型说明
ValueExistsbool __fastcall ValueExists(const UnicodeString Section, const UnicodeString Ident);判断是否存在 [Section] 里面的 Indent

删除数据

删除数据函数原型说明
DeleteKeyvoid __fastcall DeleteKey(const UnicodeString Section, const UnicodeString Ident);删除 [Section] 里面的 Indent

读取 Sections

读取 Sections函数原型说明 (示例为处理 “含有 SubSections 的 ini 文件结构” 的结构示例表格里面的 “用 . 分割 SubSections 的 ini 文件”)
ReadSectionvoid __fastcall ReadSection(const UnicodeString Section, TStrings* Strings);获取 [Section] 里面所有的 Indent,例如:读取 "Section1.SubSection2" 得到的是:
Indent8
Indent9
ReadSectionsvoid __fastcall ReadSections(TStrings* Strings);获取所有 Section 的名字,例如读取结构示例能够得到:
Section1
Section2
Section1.SubSection1
Section1.SubSection2
Section1.SubSection2.SubSubSec1
Section1.SubSection2.SubSubSec2
ReadSectionsvoid __fastcall ReadSections(const UnicodeString Section, TStrings* Strings);获取所有名字以参数 Section 指定的字符串开头的 Section 的名字。如果 Section 给定的是空字符串,执行结果和前一个只有一个参数的 ReadSections 函数相同。
ReadSubSectionsvoid __fastcall ReadSubSections(const UnicodeString Section, TStrings* Strings, bool Recurse = false);获取所有 SubSections 的名字,
例如获取 "Section1.SubSection2"
得到的是 SubSubSec1 和 SubSubSec2,
例如获取 "Section1"
得到的是 SubSection1, SubSection2, SubSection2.SubSubSec1, SubSection2.SubSubSec2
ReadSectionValuesvoid __fastcall ReadSectionValues(const UnicodeString Section, TStrings* Strings);获取 [Section] 里面所有的值,
例如获取 "Section1"
得到的是
Indent1=Value1
Indent2=Value2
SectionExistsbool __fastcall SectionExists(const UnicodeString Section);判断 [Section] 是否存在。

删除 Sections

删除 Sections函数原型说明
EraseSectionvoid __fastcall EraseSection(const UnicodeString Section);删除整个 [Section]

整体文件的数据操作

整体文件数据操作函数原型说明
Clearvoid __fastcall Clear(void);清除整个 ini 文件的内容
GetStringsvoid __fastcall GetStrings(TStrings* const List);获取整个 ini 文件的内容到 List
SetStringsvoid __fastcall SetStrings(TStrings* const List);整个 ini 的文件内容更换为 List 的内容

TMemIniFile 的属性成员

属性类型说明
AutoSavebool是否在销毁 TMemIniFile 对象时保存文件,默认为 false,不保存。
Modifiedboolini 文件数据是否被修改过
CaseSensitivebool关键字 (Section 和 Ident) 是否区分大小写
FileNameUnicodeString文件名 (只读),在创建对象时指定文件名,或者用 Rename() 改名。
EncodingTEncoding *文件的字符编码

使用 TIniFile 处理 ini 文件

在使用上,TIniFile 和 TMemIniFile 只有两点不同的地方:
 • 不需要用 UpdateFile() 存盘,也不需要指定 AutoSave 属性,TIniFile 始终和文件同步,每次读写数据都是在读写文件;
 • 不能指定字符编码,始终使用默认的编码 (ANSI) 创建新的文件,读取的时候,支持 ANSI 和 UNICODE (UTF-16)

使用 TIniFile 的注意事项:
 • 不推荐使用 TIniFile,推荐使用 TMemIniFile 处理 ini 文件;
 • TIniFile 用的是过时的 API 函数 GetPrivateProfileString 和 WritePrivateProfileString 处理的 ini 文件,在 Windows 8 和 Windows 10 操作系统里面,出现访问系统盘里面的文件的兼容性问题。MSDN 里面描述的这两个 API 函数是为了兼容 16 位 Windows 应用保留的函数。
 • TIniFile 只能新建 ANSI 编码的文件,可以读写 ANSI 和 UNICODE (UTF-16) 编码的文件,无法读写 UTF-8 或其他编码的文件。

TMemIniFile 和 TIniFile,应该使用哪一个,他们有什么区别?

用下面的表格比较 TMemIniFile 和 TIniFile,很明显 TMemIniFile 获胜,应该使用 TMemIniFile。

项目TMemIniFileTIniFile
读写方法使用 TFileStream 读写文件,支持用 TEncoding 指定字符编码使用的是过时的 GetPrivateProfileString 和 WritePrivateProfileString,这两个为了兼容 16 位 Windows 应用保留下来的 API 函数
兼容性使用的是通用的文件处理方法,没有兼容性问题在 Windows 8 之后的系统里面,读写系统盘里面的文件可能会出现无法读写文件内容的兼容性问题
文字编码使用 TEncoding,支持所有操作系统支持的文字编码,包括 UNICODE (UTF-16) 和 UTF-8新创建的 ini 文件只能是 ANSI 编码的,可以读取 ANSI 和 UNICODE (UTF-16) 的文件,无法读取 UTF-8 或其他编码的文件
效率所有的内容都在内存里面处理,速度快,效率高所有的处理都和文件同步,每次操作都读写文件,速度慢,效率低
使用区别修改之后,需要用 UpdateFile() 存盘,也可以设 AutoSave 属性为 true,在修改之后自动保存文件。其他和 TIniFile 一样不需要写存盘的代码,因为每次操作都和文件内容同步

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
= 标题: KYLib 简介 = 版本: 3.1.0.0 (build 2014.10.21) 从 KYLib 2.1.1.0 版本开始, 在类中添加详细的注释, 可以很轻松的使用类及相关属性方 法等等。 KYLib 使用简单, 只要头文件中包含有: #include "KYLib.h" 就可以了。 KYLib 有针对VC6, VS2008等版本库, 而且基于KYLib开发的代码可以在VC不同版本中平稳移 植, 甚至可以平稳移植到Linux中。 KYLib 提供的相关函数与Delphi中基本相同, 提供丰富的函数和类, 如: a. 字符串类KYString与Delphi中的String结构基本相似, 而且多线程安全稳定 b. TDateTime类型与Delphi中的TDateTime类型完全相同, 而且支持相关的函数 c. 字符串操作相关函数 {Copy, Trim, UpperCase, SetLength, Format, SameText, CompareStr等等} d. 日期时间相关函数 {Date, Time, Now, FormatDateTime等等} e. 文件操作相关函数 {FileOpen, FileCreate, FileClose, FileExists, CreateDir, DeleteFile, ExtractFilePath等等} f. 编码相关函数 {Randomize, Random, Unicode/UTF8编码, CRC32编码, Base64编码, MD5编码, 加密/解密编码等等} g. 线程相关类 {TThread, TKYThread, TKYRunThread, TKYAsynchRun, TKYTimer等等} h. 文件类 {TFile, TKYMapFile, TKYDebugFile, TKYLogObj等等} i. 文件表类 {TKYTable, TKYIndexFile, TKYIndexTree} j. ini文件类 {TIniFile, TMemIniFile等等} k. 列表类 {TKYList, TKYStringList, TKYCustomList, TKYNameStrList, TKYCode2Name 等等} l. 链表类 {TKYCycQueue, TKYQueue, TKYStack, TKYQueueEx, TKYStackEx等等} m. 句柄类 {TKYHandles, TKYMemHandles等等} n. 二叉树类 {TKYAVLTree, TKYAVLTreeEx, TKYLevelTree, AVL树相关函数} o. 共享队列类 {TKYQueueMap, TKYQueueFile, TKYQueueFileEx} p. 内存管理类 {TKYCache, TKYFormatBlock, TKYMemBlock等等} q. 线程同步类 {TKYCritSect, TKYLockRW, TKYEvent, TKYMutex, TKYSemaphore} r. 可变类型类 {TKYVarType, TKYField, TKYFieldDef等等} s. 接收缓冲区类 {KYCycBuffer, TKYRecvBuffer, TKYRecvCache} t. Socket相关类 {TKYBaseSocket, TKYSockRecvThread, TKYTCPClient, TKYTCPServer, TKYUDPClient, TKYUDPServer等等} u. 压缩/解压缩类 {TKYPack, TKYUnpack, TKYQuickPack, TKYQuckUnpack, KYFixedPack, KYFixedUnpack} v. 字符串模式匹配类 {TKYMatch} w. map 相关的类模板 {TKYMapIntKey, TKYMapStrKey, TKYMapObjKey, TKYMapIntKeyEx, TKYMapStrKeyEx, TKYMapObjKeyEx} x. 智能对象集类模板 {TKYSmartObjs, TKYAllotObjs} KYLib 是专业级类
= 标题: KYLib 简介 = 版本: 3.1.0.0 (build 2014.10.21) 从 KYLib 2.1.1.0 版本开始, 在类中添加详细的注释, 可以很轻松的使用类及相关属性方 法等等。 KYLib 使用简单, 只要头文件中包含有: #include "KYLib.h" 就可以了。 KYLib 有针对VC6, VS2008等版本库, 而且基于KYLib开发的代码可以在VC不同版本中平稳移 植, 甚至可以平稳移植到Linux中。 KYLib 提供的相关函数与Delphi中基本相同, 提供丰富的函数和类, 如: a. 字符串类KYString与Delphi中的String结构基本相似, 而且多线程安全稳定 b. TDateTime类型与Delphi中的TDateTime类型完全相同, 而且支持相关的函数 c. 字符串操作相关函数 {Copy, Trim, UpperCase, SetLength, Format, SameText, CompareStr等等} d. 日期时间相关函数 {Date, Time, Now, FormatDateTime等等} e. 文件操作相关函数 {FileOpen, FileCreate, FileClose, FileExists, CreateDir, DeleteFile, ExtractFilePath等等} f. 编码相关函数 {Randomize, Random, Unicode/UTF8编码, CRC32编码, Base64编码, MD5编码, 加密/解密编码等等} g. 线程相关类 {TThread, TKYThread, TKYRunThread, TKYAsynchRun, TKYTimer等等} h. 文件类 {TFile, TKYMapFile, TKYDebugFile, TKYLogObj等等} i. 文件表类 {TKYTable, TKYIndexFile, TKYIndexTree} j. ini文件类 {TIniFile, TMemIniFile等等} k. 列表类 {TKYList, TKYStringList, TKYCustomList, TKYNameStrList, TKYCode2Name 等等} l. 链表类 {TKYCycQueue, TKYQueue, TKYStack, TKYQueueEx, TKYStackEx等等} m. 句柄类 {TKYHandles, TKYMemHandles等等} n. 二叉树类 {TKYAVLTree, TKYAVLTreeEx, TKYLevelTree, AVL树相关函数} o. 共享队列类 {TKYQueueMap, TKYQueueFile, TKYQueueFileEx} p. 内存管理类 {TKYCache, TKYFormatBlock, TKYMemBlock等等} q. 线程同步类 {TKYCritSect, TKYLockRW, TKYEvent, TKYMutex, TKYSemaphore} r. 可变类型类 {TKYVarType, TKYField, TKYFieldDef等等} s. 接收缓冲区类 {KYCycBuffer, TKYRecvBuffer, TKYRecvCache} t. Socket相关类 {TKYBaseSocket, TKYSockRecvThread, TKYTCPClient, TKYTCPServer, TKYUDPClient, TKYUDPServer等等} u. 压缩/解压缩类 {TKYPack, TKYUnpack, TKYQuickPack, TKYQuckUnpack, KYFixedPack, KYFixedUnpack} v. 字符串模式匹配类 {TKYMatch} w. map 相关的类模板 {TKYMapIntKey, TKYMapStrKey, TKYMapObjKey, TKYMapIntKeyEx, TKYMapStrKeyEx, TKYMapObjKeyEx} x. 智能对象集类模板 {TKYSmartObjs, TKYAllotObjs} KYLib 是专业级类

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值