You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用LINQ解析INI文件:按指定节名和键名过滤的问题及通用函数实现

使用LINQ解析INI文件:按指定节名和键名过滤的问题及通用函数实现

我最近做INI文件解析的需求时遇到了一个小坑,想和大家分享下问题和最终的通用解决方案:

问题场景

我需要从INI文件中提取指定节下、指定键名开头的所有键值对,示例INI片段如下:

[INSTANCES]
NUMVTC=3
VTC=0,3330,ABCD,DESCR0
VTC=1,3331,EFGH,DESCR1
VTC=2,3332,IJKL,DESCR2

我的需求是只提取[INSTANCES]节下所有以VTC开头的键值对,跳过NUMVTC=3这一行。

初始代码的问题

一开始我写了下面的LINQ代码,但发现加上VTC的判断后,代码直接返回空列表;去掉VTC判断的话,又会把NUMVTC=3也包含进来:

List<IniEntry> vals = File.ReadLines(sMappingFilePath)
    .SkipWhile(line => !line.StartsWith("[instances]", StringComparison.CurrentCultureIgnoreCase))
    .Skip(1)
    .TakeWhile(line => !string.IsNullOrEmpty(line) && line.StartsWith("vtc", StringComparison.CurrentCultureIgnoreCase)) // 这行判断导致代码失效
    .Select(line => new IniEntry(line.Split('=')[0], line.Split('=')[1])).ToList();

public class IniEntry {
    public string Key { get; set; }
    public string Value { get; set; }
    public IniEntry(string key, string val) {
        Key = key;
        Value = val;
    }
}

问题原因

仔细分析TakeWhile的逻辑就懂了:它会持续读取行直到某一行不满足条件。而节下面的第一行是NUMVTC=3,它并不以VTC开头,所以TakeWhile在遇到这一行时直接停止取值,后面的VTC行根本不会被处理,自然返回空列表。

通用解决方案

后来我调整了逻辑,把过滤条件从TakeWhile移到Where中,同时封装成了通用函数,支持传入任意INI路径、节名和键名,返回符合条件的IniEntry列表:

public static List<IniEntry> GetIniSectionDataList(string sIniFilePath, string sSection, string sKey) {
    List<IniEntry> ls = new List<IniEntry>();
    if (string.IsNullOrEmpty(sIniFilePath)) {
        return ls;
    }

    // 兼容用户输入的节名带[]或不带的情况
    sSection = sSection.Replace("[", string.Empty).Replace("]", string.Empty);
    sSection = "[" + sSection + "]";

    ls = File.ReadLines(sIniFilePath)
        // 定位到目标节的起始位置
        .SkipWhile(line => !line.StartsWith(sSection, StringComparison.CurrentCultureIgnoreCase))
        // 筛选出非空且以指定键名开头的行
        .Where(line => !string.IsNullOrEmpty(line) && line.StartsWith(sKey, StringComparison.CurrentCultureIgnoreCase))
        // 转换为IniEntry对象
        .Select(line => new IniEntry(line.Split('=')[0], line.Split('=')[1]))
        .ToList();

    return ls;
}

// 调用示例
List<IniEntry> vals = TCLogFile.GetIniSectionDataList(sMappingFilePath, "instances", "vtc");

关键改进点

  1. 节名兼容处理:自动移除用户输入的[]符号再重新拼接,不管用户传"instances"还是"[instances]"都能正确识别目标节。
  2. 过滤逻辑调整:把键名过滤从TakeWhile改为Where,Where会遍历节下的所有行,只筛选符合键名条件的行,不会因为某一行不符合就停止后续处理。
  3. 简化流程:移除了多余的Skip(1),因为节名行本身不会满足键名过滤条件,会被自动跳过。

现在这个通用函数可以完美满足需求:传入节名和键名,就能精准提取INI文件中符合条件的所有键值对啦。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.08 07:18:06