使用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");
关键改进点
- 节名兼容处理:自动移除用户输入的
[]符号再重新拼接,不管用户传"instances"还是"[instances]"都能正确识别目标节。 - 过滤逻辑调整:把键名过滤从
TakeWhile改为Where,Where会遍历节下的所有行,只筛选符合键名条件的行,不会因为某一行不符合就停止后续处理。 - 简化流程:移除了多余的
Skip(1),因为节名行本身不会满足键名过滤条件,会被自动跳过。
现在这个通用函数可以完美满足需求:传入节名和键名,就能精准提取INI文件中符合条件的所有键值对啦。
内容来源于stack exchange
相关产品推荐
相关产品推荐

