前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >配置文件格式 INI 快速上手

配置文件格式 INI 快速上手

作者头像
恋喵大鲤鱼
发布2024-07-22 07:58:56
840
发布2024-07-22 07:58:56
举报
文章被收录于专栏:C/C++基础

1.简介

INI 的全称是 Initialization,即为初始化文件,最早是 Windows 系统配置文件所采用的格式。

有时候,INI 文件也会以不同的扩展名出现,如 .cfg、.conf、或 .txt。但为了可读性,不建议这么做。

因为 INI 并没有一个统一的官方标准,所以这里介绍常见的 INI 文件格式惯例。

2.语法

INI 是一种简单实用且应用广泛的配置文件格式,通常由节、键值对和注释组成。

节(Section)是键值对的分组。

一般情况下,节是可选的,不属于任何节的配置项属于全局配置项。

所有的 Section 名称都是独占一行,并且 Section 名字都被方括号 [] 包围。在 Section 声明后的所有键值对都属于该 Section。一个 Section 没有明显的结束标识符,一个 Section 的开始就是上一个 Section 的结束。

代码语言:javascript
复制
[section]

注意,不同节之间的变量可以同名。

正因为没有显式的“节结束符”(例如 XML 的</tag>)。因此,节在语法上不能任意嵌套。必要时,可以将层次结构扁平化,使用分隔符分隔多个节名(通常使用点 . 分隔)来实现嵌套。一级嵌套通常是支持的,称为子节。

代码语言:javascript
复制
[section]
domain = example.com

[section.subsection]
foo = bar

键值对

每一个键值对表示一项配置,键与值使用等号分隔。

代码语言:javascript
复制
name=value

注释

注释以分号(;)开头,有一些 INI 管理器也支持使用井号(#)来注释。

代码语言:javascript
复制
; this is comment text

大小写

Windows 中的节和键名是不区分大小写的。大多数 Unix 风格的 INI 解析器也完全不区分大小写。

尽管部分 INI 解析器是支持大小写的,但为了良好的可读性,不建议这么做。

空白行

空白行通常被忽略,可以用来提高可读性。

数据类型

INI 文件格式的设计非常简单,不像 YAML、TOML 等更现代的配置文件格式那样明确支持多种数据类型。通常,INI 文件中的所有数据都是以字符串的形式存储的。然而,不同的解析器可能会尝试根据内容自动识别并转换数据类型。

字符串 (String)

默认情况下,所有值都被视为字符串。字符串值可以包含任何字符。

字符串值通常不需要引号,但在某些情况下可以使用引号(单引号或双引号)括起来。

代码语言:javascript
复制
key1=value1
key2=some text with spaces
key3="quoted string"
整数 (Integer)

一些解析器会尝试将纯数字的值解析为整数。

代码语言:javascript
复制
key1=42
key2=-3
浮点数 (Float)

类似地,包含小数点的数字可能会被解析为浮点数。

代码语言:javascript
复制
[Section]
key1=3.14
key2=-0.001
布尔值 (Boolean)

常见的布尔值表示法包括 true, false, yes, no, 1, 和 0。许多解析器会自动将这些值转换为布尔类型。

代码语言:javascript
复制
key1=true
key2=no
key3=1
key4=0
列表 (List)

虽然 INI 文件格式本身不直接支持列表,但可以通过使用分隔符(如逗号或分号)来模拟列表。某些解析器可以将这些值分割成列表。

代码语言:javascript
复制
key1=value1,value2,value3
key2=item1;item2;item3

3.示例

由于没有官方标准,建议在使用 INI 文件时遵循你所使用的解析器的具体规范,并保持文件结构的简单和一致。

以下是一个综合示例:

代码语言:javascript
复制
; Global section settings
globalKey1=value1

[Section1]
# Section1 specific settings
key1=value1
key2=value2

[Section2]
key1=value3  # Section2 specific settings
key3=value4

4.解析

下面是一个使用键值对表示的后台服务配置。

代码语言:javascript
复制
; server basic conf
[server]
name=UserProfileServer
maxconns=10000
queuecap=10000
queuetimeout=300

# log conf
[log]
loglevel=ERROR
logsize=10M
lognum=10
logpath=/usr/local/app/log

在解析上面的配置时,可以按行读取,然后放到 map 中。

下面以 Go 为例,完成对上面配置文件的解析。

代码语言:javascript
复制
package main

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"os"
	"strings"
)

func ParseConf(confPath string) (map[string]string, error) {
	if confPath == "" {
		return nil, errors.New("param is ill")
	}

	f, err := os.Open(confPath)
	if err != nil {
		return nil, err
	}
	defer f.Close()

	// store config info
	m := make(map[string]string)

	bfRd := bufio.NewReader(f)
	// read by line, the line terminator is '\n'
	for {
		line, err := bfRd.ReadString('\n')
		if err == io.EOF {
			return m, nil
		}
		if err != nil {
			return nil, err
		}
		// ignore blank line
		if strings.TrimSpace(line) == "" {
			continue
		}
		// ignore comment line
		if strings.TrimSpace(line)[0] == ';' || strings.TrimSpace(line)[0] == '#' {
			continue
		}
		// ignore section line
		if strings.TrimSpace(line)[0] == '[' {
			continue
		}
		kv := strings.Split(strings.TrimSpace(line), "=")
		if len(kv) == 2 {
			m[kv[0]] = kv[1]
		}
	}
}

func main() {
	conf, _ := ParseConf("server.ini")
	for k, v := range conf {
		fmt.Printf("%v=%v\n", k, v)
	}
}

运行结果:

代码语言:javascript
复制
name=UserProfileServer
maxconns=1000
queuecap=10000
queuetimeout=300
loglevel=ERROR
logsize=10M
lognum=10

推荐使用专业的第三方库来完成 INI 的解析,比如 Golang 中强大的 spf13/viper

代码语言:javascript
复制
package main

import (
	"fmt"

	"github.com/spf13/viper"
)

func main() {
	// 设置配置文件的名称和路径
	viper.SetConfigName("server.ini") // 可以不写文件扩展名
	viper.AddConfigPath("..")         // 在当前目录查找配置文件

	// 设置配置文件类型为 INI
	viper.SetConfigType("ini")

	// 读取配置文件
	if err := viper.ReadInConfig(); err != nil {
		fmt.Printf("Error reading config file, %s", err)
		return
	}

	// 获取配置项的值
	fmt.Println("server.name:", viper.GetString("server.name"))
	fmt.Println("server.maxconns:", viper.GetInt("server.maxconns"))
	fmt.Println("server.queuecap:", viper.GetInt("server.queuecap"))
	fmt.Println("server.queuetimeout:", viper.GetInt("server.queuetimeout"))

	fmt.Println("log.loglevel:", viper.GetString("log.loglevel"))
	fmt.Println("log.logsize:", viper.GetString("log.logsize"))
	fmt.Println("log.lognum:", viper.GetInt("log.lognum"))
	fmt.Println("log.logpath:", viper.GetString("log.logpath"))
}

运行结果:

代码语言:javascript
复制
server.name: UserProfileServer
server.maxconns: 10000
server.queuecap: 10000
server.queuetimeout: 300
log.loglevel: ERROR
log.logsize: 10M
log.lognum: 10
log.logpath: /usr/local/app/log

参考文献

INI file - wikipedia Apache Documentation for org.apache.commons.configuration2.INIConfiguration

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-07-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.简介
  • 2.语法
      • 键值对
        • 注释
          • 大小写
            • 空白行
              • 数据类型
                • 字符串 (String)
                • 整数 (Integer)
                • 浮点数 (Float)
                • 布尔值 (Boolean)
                • 列表 (List)
            • 3.示例
            • 4.解析
            • 参考文献
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档