INI文件的语法简单,结构清晰,便于阅读。网上有很多INI文件相关的资料,但是很少有看到说明INI文件的起源和发展的文章。其实我也好奇这点,接下来,我就先介绍INI文件的起源和发展,然后介绍INI文件的语法,以及Qt中如何读取和编辑INI文件。
INI文件的起源和发展
INI文件的概念最早由Microsoft在20世纪80年代提出并使用在早期的Windows操作系统中。INI文件的设计初衷是为了存储应用程序的配置数据。“INI"一词是"Initialization”(初始化)的缩写。
当时的Windows操作系统并没有统一的配置文件格式,每个应用程序都需要自己实现配置文件的读取和写入。为了解决这个问题,Microsoft引入了INI文件作为一种通用的配置文件格式,以简单的键值对的方式存储配置数据。
INI文件的设计初衷是为了提供一种轻量级、易于编辑和解析的配置文件格式。之后,INI文件成为了Windows系统中常见的配置文件格式,并被许多应用程序广泛采用。
虽然INI文件最早由Microsoft引入,并在Windows系统中得到广泛应用,但INI文件的概念和实现方式也被其他操作系统和应用程序所采用和扩展。不同的操作系统和应用程序可能会对INI文件有些许的差异和扩展,但基本的键值对结构和语法规则基本保持一致。
INI文件的作用
INI文件(Initialization File)是一种用于存储配置数据的文本文件格式。它通常以简单的键值对(Key-Value)的形式组织数据,用于保存应用程序的各种设置和选项。例如:数据库连接配置、网络设置、界面风格、语言选择等。通过读取和修改INI文件,用户和开发者可以轻松地配置和个性化应用程序,满足特定的需求。
INI文件的语法
INI文件的语法非常简单,它是以文本形式存储配置数据的一种格式。下面是INI文件的常见语法规则:
节 (Section) | 节用方括号[ ]括起来,用于区分不同的配置项,例如:[section1]。节名可以是任何字符和数字的组合,但一般建议使用有意义的名称。 |
键值对 (key-value) | 键值对是配置项的基本元素,用于存储具体的配置数据。键(Key)和值(Value)之间用等号(=)或冒号(:)分隔。例如:Key1=Value1 。 |
注释 (Comment) | 注释用来添加对配置项的说明,不会被程序读取。在INI文件中,以分号(;)或井号(#)开头的行都被视为注释。例如:; 我是注释我是注释 。 |
空行 (Blank Line) | 空行不包含任何内容,通常用于提高文件的可读性。 |
字符串 (string) | 键和值可以是任何文本,包括字母、数字、标点符号等。字符串可以使用引号(单引号或双引号)括起来,也可以不括起来。 |
注意:INI文件不一定都是以 .ini 为文件后缀名。其他常见的后缀名还有:.cfg .conf
INI文件的后缀名并没有严格的规定,不同的应用程序或操作系统可能会使用不同的后缀名。因此,在具体的应用程序或系统中,可能会存在其他的INI文件后缀名。
关于嵌套节
在标准的INI文件格式中,并没有直接支持嵌套节的概念。每个节都是独立的,并且没有层次结构。
然而,一些解析INI文件的库或工具提供了对嵌套节的支持,通过特定的约定或语法扩展来模拟嵌套的结构。这样可以在节内部创建子节或子命名空间,以更好地组织和表示配置数据。
例如,可以使用点号 .
或大括号 {} 来表示嵌套的节。下面是一个示例:
[Section1]
Key1=Value1
[Section1.Subsection1]
Key2=Value2
[Section1.Subsection2]
Key3=Value3
使用这种约定或语法,可以在Section1节内部创建子节SubSection1和SubSection2,从而实现嵌套的节结构。
需要注意的是,嵌套节的使用可能会依赖于具体的解析器或库,不同的工具对语法的支持和解析方式可能有所不同。因此,在使用嵌套节时,应该遵循相应工具的文档和准则,并确保解析器能够正确解释INI文件中的嵌套节。
这里不讨论嵌套节。
INI文件解析
Qt中有QSettings默认支持INI文件,除了INI文件之外,QSettings还支持Json、XML、注册表(windows特定)、SQLite数据库格式等。QSettings::Format 枚举类型中包含了QSettings支持的文件格式。
在电脑中找到了一个迅雷的配置文件,内容如下:
[MainFrame]
ExitType=normal
ExitState=normal
MainWndLastWidth=1060
MainWndLastHeight=650
[MainBody]
ExitType=normal
ExitState=normal
MainWndLastWidth=1120
MainWndLastHeight=680
读
void initest::iniRead(){
QSettings settings("路径/Thunder.ini",QSettings::IniFormat);
qDebug()<<settings.allKeys()<<settings.fileName();
qDebug()<<settings.status();
settings.beginGroup("MainFrame");
QString frameExitType=settings.value("ExitType").toString();
QString frameExitState=settings.value("ExitState").toString();
int frameMainWndLastWidth=settings.value("MainWndLastWidth").toInt();
int frameMainWndLastHeight=settings.value("MainWndLastHeight").toInt();
qDebug()<<"frameExitType:"<<frameExitType;
qDebug()<<"frameExitState:"<<frameExitState;
qDebug()<<"frameMainWndLastWidth:"<<frameMainWndLastWidth;
qDebug()<<"frameMainWndLastHeight:"<<frameMainWndLastHeight;
settings.endGroup();
QString bodyExitType=settings.value("MainBody/ExitType").toString();
QString bodyExitState=settings.value("MainBody/ExitState").toString();
int bodyMainWndLastWidth=settings.value("MainBody/MainWndLastWidth").toInt();
int bodyMainWndLastHeight=settings.value("MainBody/MainWndLastHeight").toInt();
qDebug()<<"bodyExitType:"<<bodyExitType;
qDebug()<<"bodyExitState:"<<bodyExitState;
qDebug()<<"bodyMainWndLastWidth:"<<bodyMainWndLastWidth;
qDebug()<<"bodyMainWndLastHeight:"<<bodyMainWndLastHeight;
//可以看到使用beginGroup再使用其中的键查找值和直接使用 组名/键 效果是一样的
}
运行结果:
QList("MainBody/ExitState", "MainBody/ExitType", "MainBody/MainWndLastHeight", "MainBody/MainWndLastWidth", "MainFrame/ExitState", "MainFrame/ExitType", "MainFrame/MainWndLastHeight", "MainFrame/MainWndLastWidth") "E:/000CProjects/SQLTest/SQLTest/ini/Thunder.ini"
QSettings::NoError
frameExitType: "normal"
frameExitState: "normal"
frameMainWndLastWidth: 1060
frameMainWndLastHeight: 650
bodyExitType: "normal"
bodyExitState: "normal"
bodyMainWndLastWidth:1120
bodyMainWndLastHeight: 680
写(创建)
void initest::iniWrite(){
QSettings settings("路径/Thunder1.ini",QSettings::IniFormat);
settings.beginGroup("MainFrame");
settings.setValue("ExitType","normal");
settings.setValue("ExitState","normal");
settings.setValue("MainWndLastWidth",1060);
settings.setValue("MainWndLastHeight",650);
settings.endGroup();
settings.setValue("BodyFrame/ExitType","normal");
settings.setValue("BodyFrame/ExitState","normal");
settings.setValue("BodyFrame/MainWndLastWidth",1120);
settings.setValue("BodyFrame/MainWndLastHeight",680);
settings.sync();
}
运行结果:
修改
void initest::iniModify(){
QSettings settings(GLOBAL::INIPath()+"/Thunder.ini",QSettings::IniFormat);
settings.beginGroup("MainFrame");
settings.setValue("MainWndLastWidth",666);
settings.endGroup();
settings.setValue("MainBody/MainWndLastHeight",888);
settings.sync();
}
运行结果:
通过上面的测试,可以看出,在setValue时,如果该键值对存在,就修改原有的值,如果不存在就新建键值对。