matlab读取ini文件文本,Go语言从INI配置文件中读取需要的值

INI 文件是 Initialization File 的缩写,即初始化文件,是 Windows 的系统配置文件所采用的存储格式,统管 Windows 的各项配置。INI 文件格式由节(section)和键(key)构成,一般用于操作系统、虚幻游戏引擎、GIT 版本管理中,这种配置文件的文件扩展名为.ini。

下面是从 GIT 版本管理的配置文件中截取的一部分内容,展示 INI 文件的样式。

[core]

repositoryformatversion = 0

filemode = false

bare = false

logallrefupdates = true

symlinks = false

ignorecase = true

hideDotFiles = dotGitOnly

[remote "origin"]

url = https://github.com/davyxu/cellnet

fetch = +refs/heads/*:refs/remotes/origin/*

[branch "master"]

remote = origin

merge = refs/heads/master

INI 文件的格式

INI 文件由多行文本组成,整个配置由[ ]拆分为多个“段”(section)。每个段中又以=分割为“键”和“值”。

INI 文件以;置于行首视为注释,注释后将不会被处理和识别,如下所示:

[sectionl]

key1=value1

;key2=value2

[section2]

从 INI 文件中取值的函数

熟悉了 INI 文件的格式后,下面我们创建一个 example.ini 文件,并将从 GIT 版本管理配置文件中截取的一部分内容复制到该文件中。

准备好 example.ini 文件后,下面我们开始尝试读取该 INI 文件,并从文件中获取需要的数据,完整的示例代码如下所示:

package main

import (

"bufio"

"fmt"

"os"

"strings"

)

// 根据文件名,段名,键名获取ini的值

func getValue(filename, expectSection, expectKey string) string {

// 打开文件

file, err := os.Open(filename)

// 文件找不到,返回空

if err != nil {

return ""

}

// 在函数结束时,关闭文件

defer file.Close()

// 使用读取器读取文件

reader := bufio.NewReader(file)

// 当前读取的段的名字

var sectionName string

for {

// 读取文件的一行

linestr, err := reader.ReadString('\n')

if err != nil {

break

}

// 切掉行的左右两边的空白字符

linestr = strings.TrimSpace(linestr)

// 忽略空行

if linestr == "" {

continue

}

// 忽略注释

if linestr[0] == ';' {

continue

}

// 行首和尾巴分别是方括号的,说明是段标记的起止符

if linestr[0] == '[' && linestr[len(linestr)-1] == ']' {

// 将段名取出

sectionName = linestr[1 : len(linestr)-1]

// 这个段是希望读取的

} else if sectionName == expectSection {

// 切开等号分割的键值对

pair := strings.Split(linestr, "=")

// 保证切开只有1个等号分割的简直情况

if len(pair) == 2 {

// 去掉键的多余空白字符

key := strings.TrimSpace(pair[0])

// 是期望的键

if key == expectKey {

// 返回去掉空白字符的值

return strings.TrimSpace(pair[1])

}

}

}

}

return ""

}

func main() {

fmt.Println(getValue("example.ini", "remote \"origin\"", "fetch"))

fmt.Println(getValue("example.ini", "core", "hideDotFiles"))

}

本例并不是将整个 INI 文件读取保存后再获取需要的字段数据并返回,这里使用 getValue() 函数,每次从指定文件中找到需要的段(Section)及键(Key)对应的值。

getValue() 函数的声明如下:

func getValue(filename, expectSection, expectKey string) string

参数说明如下。

filename:INI 文件的文件名。

expectSection:期望读取的段。

expectKey:期望读取段中的键。

getValue() 函数的实际使用例子参考代码如下:

func main() {

fmt.Println(getValue("example.ini", "remote \"origin\"", "fetch"))

fmt.Println(getValue("example.ini", "core", "hideDotFiles"))

}

运行上面的示例程序,输出结果如下:

+refs/heads/*:refs/remotes/origin/*

dotGitOnly

输出内容中“+refs/heads/*:refs/remotes/origin/*”表示 INI 文件中[remote "origin"]的 "fetch" 键对应的值;dotGitOnly 表示 INI 文件中[core]中键名为 "hideDotFiles" 的值。

注意 main 函数的第 2 行中,由于段名中包含双引号,所以使用\进行转义。

getValue() 函数的逻辑由 4 部分组成:即读取文件、读取行文本、读取段和读取键值组成。接下来分步骤了解 getValue() 函数的详细处理过程。

读取文件

Go语言的 OS 包中提供了文件打开函数 os.Open(),文件读取完成后需要及时关闭,否则文件会发生占用,系统无法释放缓冲资源。参考下面代码:

// 打开文件

file, err := os.Open(filename)

// 文件找不到,返回空

if err != nil {

return ""

}

// 在函数结束时,关闭文件

defer file.Close()

代码说明如下:

第 2 行,filename 是由 getValue() 函数参数提供的 INI 的文件名。使用 os.Open() 函数打开文件,如果成功打开,会返回文件句柄,同时返回打开文件时可能发生的错误:err。

第 5 行,如果文件打开错误,err 将不为 nil,此时 getValue() 函数返回一个空的字符串,表示无法从给定的 INI 文件中获取到需要的值。

第 10 行,使用 defer 延迟执行函数,defer 并不会在这一行执行,而是延迟在任何一个 getValue() 函数的返回点,也就是函数退出的地方执行。调用 file.Close() 函数后,打开的文件就会被关闭并释放系统资源。

INI 文件已经打开了,接下来就可以开始读取 INI 的数据了。

读取行文本

INI 文件的格式是由多行文本组成,因此需要构造一个循环,不断地读取 INI 文件的所有行。Go语言总是将文件以二进制格式打开,通过不同的读取方式对二进制文件进行操作。Go语言对二进制读取有专门的代码,bufio 包即可以方便地以比较常见的方式读取二进制文件。

// 使用读取器读取文件

reader := bufio.NewReader(file)

// 当前读取的段的名字

var sectionName string

for {

// 读取文件的一行

linestr, err := reader.ReadString('\n')

if err != nil {

break

}

// 切掉行的左右两边的空白字符

linestr = strings.TrimSpace(linestr)

// 忽略空行

if linestr == "" {

continue

}

// 忽略注释

if linestr[0] == ';' {

continue

}

//读取段和键值的代码

//...

}

代码说明如下:

第 2 行,使用 bufio 包提供的 NewReader() 函数,传入文件并构造一个读取器。

第 5 行,提前声明段的名字字符串,方便后面的段和键值读取。

第 7 行,构建一个读取循环,不断地读取文件中的每一行。

第 10 行,使用 reader.ReadString() 从文件中读取字符串,直到碰到\n,也就是行结束。这个函数返回读取到的行字符串(包括\n)和可能的读取错误 err,例如文件读取完毕。

第 16 行,每一行的文本可能会在标识符两边混杂有空格、回车符、换行符等不可见的空白字符,使用 strings.TrimSpace() 可以去掉这些空白字符。

第 19 行,可能存在空行的情况,继续读取下一行,忽略空行。

第 24 行,当行首的字符为;分号时,表示这一行是注释行,忽略一整行的读取。

读取 INI 文本文件时,需要注意各种异常情况。文本中的空白符就是经常容易忽略的部分,空白符在调试时完全不可见,需要打印出字符的 ASCII 码才能辨别。

抛开各种异常情况拿到了每行的行文本 linestr 后,就可以方便地读取 INI 文件的段和键值了。

读取段

行字符串 linestr 已经去除了空白字符串,段的起止符又以[开头,以]结尾,因此可以直接判断行首和行尾的字符串匹配段的起止符匹配时读取的是段,如下图所示。

bdf4606f4f7fd9c17077e9a9ed376996.gif

图:INI 文件的段名解析

此时,段只是一个标识,而无任何内容,因此需要将段的名字取出保存在 sectionName(己在之前的代码中定义)中,待读取段后面的键值对时使用。

// 行首和尾巴分别是方括号的,说明是段标记的起止符

if linestr[0] == '[' && linestr[len(linestr)-1] == ']' {

// 将段名取出

sectionName = linestr[1 : len(linestr)-1]

// 这个段是希望读取的

}

代码说明如下:

第 2 行,linestr[0]表示行首的字符,len(linestr)-1取出字符串的最后一个字符索引随后取出行尾的字符。根据两个字符串是否匹配方括号,断定当前行是否为段。

第 5 行,linestr 两边的[和]去掉,取出中间的段名保存在 sectionName 中,留着后面的代码用。

读取键值

这里代码紧接着前面的代码。当前行不是段时(不以[开头),那么行内容一定是键值对。别忘记此时 getValue() 的参数对段有匹配要求。找到能匹配段的键值对后,开始对键值对进行解析,参考下面的代码:

else if sectionName == expectSection {

// 切开等号分割的键值对

pair := strings.Split(linestr, "=")

// 保证切开只有1个等号分割的简直情况

if len(pair) == 2 {

// 去掉键的多余空白字符

key := strings.TrimSpace(pair[0])

// 是期望的键

if key == expectKey {

// 返回去掉空白字符的值

return strings.TrimSpace(pair[1])

}

}

}

代码说明如下:

第 1 行,当前的段匹配期望的段时,进行后面的解析。

第 4 行,对行内容(linestr)通过 strings.Split() 函数进行切割,INI 的键值对使用=分割,分割后 strings.Split() 函数会返回字符串切片,其类型为 []string。这里只考虑一个=的情况,因此被分割后 strings.Split() 函数返回的字符串切片有 2 个元素。

第 7 行,只考虑切割出 2 个元素的情况。其他情况会被忽略, 键值如没有=、行中多余一个=等情况。

第 10 行,pair[0] 表示=左边的键。使用 strings.TrimSpace() 函数去掉空白符,如下图所示。

第 13 行,键值对切割出后,还需要判断键是否为期望的键。

第 16 行,匹配期望的键时,将 pair[1] 中保存的键对应的值经过去掉空白字符处理后作为函数返回值返回。

a95a09b31face609cd0474a1ca2e5c76.gif

图:lNI 的键值解析

  • 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、付费专栏及课程。

余额充值