Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/339.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
解析配置文件C#_C#_Parsing - Fatal编程技术网

解析配置文件C#

解析配置文件C#,c#,parsing,C#,Parsing,我需要一些帮助来解析包含多个部分的文本文件。该文件的格式如下: ;This is a comment that should be ignored when parsing ;Colors in 24-bit format #define BLUE 16711680 #define RED 255 [SETTINGS] File Name File Description v1.0 [SECTION] BLUE N033.56.09.699 W118.25.09.714 [SECTI

我需要一些帮助来解析包含多个部分的文本文件。该文件的格式如下:

;This is a comment that should be ignored when parsing 

;Colors in 24-bit format
#define BLUE 16711680
#define RED 255

[SETTINGS]
File Name
File Description
v1.0

[SECTION]
BLUE  N033.56.09.699 W118.25.09.714

[SECTION2]
RED    N033.56.13.675 W118.24.30.908
       N033.56.13.675 W118.24.30.908
       N033.56.16.034 W118.24.07.905
基本上,我需要跳过任何评论。我还需要能够从#define部分提取子值。最后,我需要分析每个标题部分下的每一行(例如,
[SETTINGS]
[section]
,等等)。该文件不仅限于这些标题

这是我现在拥有的,但显然不起作用

string line;
while ((line = reader.ReadLine()) != null)
{
    string[] items = line.Split('\t');
    foreach (string item in items)
    {
        if(item.StartsWith("[SETTINGS]"))
        {

        }
        if(item.StartsWith("[SECTIOn]"))
        {

        }
    }
}

不想测试它,但这里是一个开始:

string line;
Dictionary Define<string, int> = new Dictionary<string, int>();

while ((line = reader.ReadLine()) != null)
{
   if(line.StartsWith(";"))
   {
      continue;
   }

   if(line.StartsWith("#define")
   {
      string[] defineItems = line.Split();
      Define[defineItems[1]] = defineItems[2];
      continue;
   }

   if(line.StartsWith("[SETTINGS]"))
        {

        }
        if(item.StartsWith("[SECTIOn]"))
        {

        }

}
字符串行;
字典定义=新字典();
而((line=reader.ReadLine())!=null)
{
if(带(;)的行开始)
{
继续;
}
if(第行开始使用(“#定义”)
{
字符串[]defineItems=line.Split();
定义[defineItems[1]]=defineItems[2];
继续;
}
if(行.StartsWith(“[SETTINGS]”)
{
}
if(项目开始时带有(“[部分]”)
{
}
}

为了便于阅读,我在字典中对章节进行了不同的操作-当您开始添加章节时,
if
语句将变成一个可维护性的噩梦。我使用控制台进行了测试,因此这在代码方面有点不完善。简言之:

查看该记录是否为
#定义
记录,如果是,则将其拆分为名称和值字符串集

如果记录是代码注释记录,请跳过

如果记录以字典键中的任何内容开头,请将当前部分更新为该内容。因此,当您看到
[Settings]
时,当前操作将是
更新设置配置
,当您看到
[section]
时,当前操作将是
更新设置

当记录不是注释、定义或节头时,它将调用应用于最近定义的节头的操作并允许处理该操作。如果用户淘气并且在文件中的多个位置定义
[设置]
,这也很方便

class Program {
    private const string ConfigComment = ";";
    private const string ConfigDefine = "#define";
    private static readonly KeyValuePair<string, Action<string>> DefaultActionValuePair = new KeyValuePair<string, Action<string>>();
    private static readonly Dictionary<string, Action<string>> settingSection = new Dictionary<string, Action<string>>(){
            { "[SETTINGS]", UpdateSettingsConfiguration}
            { "[Section]", UpdateSectionConfiguration}
        };
    static void Main() {

        StreamReader reader = new StreamReader("input.txt");
        string currentLine = reader.ReadLine();
        Action<string> currentSection = null;
        do {
            if (currentLine.StartsWith(ConfigDefine)) { //Definitions are used different than the rest of the config file, handle them special.
                string[] definition = currentLine.Substring(ConfigDefine.Length + 1).Split(' ');

                AddDefinitions(definition[0], definition[1]);
            } else if (!currentLine.StartsWith(ConfigComment)) {

                var kvp =
                    settingSection.FirstOrDefault(
                        x => x.Key.StartsWith(currentLine, StringComparison.InvariantCultureIgnoreCase));
                if (kvp.Equals(DefaultActionValuePair)) {


                    if (currentSection == null) {
                        //Invalid setting
                    } else {
                        currentSection(currentLine);
                    }
                } else {
                    currentSection = kvp.Value;
                }
            }
            currentLine = reader.ReadLine();

        } while (!reader.EndOfStream);
    }

    private static void AddDefinitions(string p1, string p2) {
        //Do stuff here
    }

    static void UpdateSettingsConfiguration(string setting) {
        //do stuff here
    }
    static void UpdateSectionConfiguration(string setting) {
        //do stuff here
    }
}
类程序{
私有常量字符串ConfigComment=“;”;
私有常量字符串ConfigDefine=“#define”;
私有静态只读KeyValuePair DefaultActionValuePair=新KeyValuePair();
私有静态只读字典设置section=newdictionary(){
{“[设置]”,更新设置配置}
{“[Section]”,UpdateSectionConfiguration}
};
静态void Main(){
StreamReader=新的StreamReader(“input.txt”);
字符串currentLine=reader.ReadLine();
Action currentSection=null;
做{
如果使用的(currentLine.StartsWith(ConfigDefine)){//定义与配置文件的其余部分不同,请对其进行特殊处理。
string[]definition=currentLine.Substring(ConfigDefine.Length+1).Split(“”);
添加定义(定义[0],定义[1]);
}如果(!currentLine.StartsWith(ConfigComment)){
var kvp=
设置Section.FirstOrDefault(
x=>x.Key.StartsWith(currentLine,StringComparison.InvariantCultureIgnoreCase));
if(kvp.Equals(DefaultActionValuePair)){
如果(currentSection==null){
//无效设置
}否则{
电流部分(电流线);
}
}否则{
currentSection=kvp.值;
}
}
currentLine=reader.ReadLine();
}而(!reader.EndOfStream);
}
私有静态void AddDefinitions(字符串p1、字符串p2){
//在这里做事
}
静态无效更新设置配置(字符串设置){
//在这里做事
}
静态void UpdateSectionConfiguration(字符串设置){
//在这里做事
}
}

如果这是您想要的数据结构类型,您可以使用下面的代码

void Main()
{
    // Gets rid of any comments that exist in our config file
    IEnumerable<string> textLines = text.Split('\n')
                                        .Where(line => !line.StartsWith(";"));;

    // Converts our 'IEnumerable<string> textLines' back to a string without comments
    string textWithoutComments = string.Join("\n", textLines);

    // Retrieves which variables are defined
    // >> BLUE 16711680 
    // >> RED 255 
    Dictionary<string, string> definedVariables = textLines .Where(line => line.StartsWith(@"#define"))
                                                            .Select(line => Regex.Match(line, @"#define ([^ ]*) (.*)"))
                                                            .ToDictionary(match => match.Groups[1].Value, match => match.Groups[2].Value);

    // Creates a dictionary of sections that have been defined
    // >> SETTINGS      File Name
    // >>               File Description
    // >>               v1.0
    // >>
    // >> SECTION BLUE  N033.56.09.699 W118.25.09.714
    // >>
    // >> SECTION2 RED  N033.56.13.675 W118.24.30.908
    // >>               N033.56.13.675 W118.24.30.908
    // >>               N033.56.16.034 W118.24.07.905 
    Dictionary<string, string> sectionDictionary = Regex.Matches(textWithoutComments, @"\[([\w]*)\]\n([^\[^\#]*)")
                                                        .Cast<Match>()
                                                        .ToDictionary(match => match.Groups[1].Value, match => match.Groups[2].Value);


    UserConfiguration userConfig = new UserConfiguration 
    {
        Variables = definedVariables,
        Settings  = sectionDictionary["SETTINGS"],
        Sections  = sectionDictionary.Where(dictionary  => dictionary.Key != "SETTINGS")
                                    .Select(dictionary  => new {Key = dictionary.Key, Value = Regex.Match(dictionary.Value, @"(\w*) ([^\[]*)")})
                                    .ToDictionary(anon => anon.Key, anon => new Config 
                                    { 
                                        Name = anon.Value.Groups[1].Value, 
                                        Value = anon.Value.Groups[2].Value.RemoveWhiteSpace()
                                    })
    };

}
public class UserConfiguration
{
    public Dictionary<string, string> Variables { get; set; }
    public string Settings { get; set; }
    public Dictionary<string, Config> Sections { get; set; }
}

public class Config
{
    public string Name { get; set; }
    public string Value { get; set; }
}

public static class Extensions
{
    public static string RemoveWhiteSpace(this string text)
    {
        var lines = text.Split('\n');
        return string.Join("\n", lines.Select(str => str.Trim()));
    }
}

const string text = @";This is a comment that should be ignored when parsing 

;Colors in 24-bit format
#define BLUE 16711680
#define RED 255

[SETTINGS]
File Name
File Description
v1.0

[SECTION]
BLUE  N033.56.09.699 W118.25.09.714

[SECTION2]
RED    N033.56.13.675 W118.24.30.908
    N033.56.13.675 W118.24.30.908
    N033.56.16.034 W118.24.07.905";

void Main()
{
//清除配置文件中存在的任何注释
IEnumerable textLines=text.Split('\n')
.Where(line=>!line.StartsWith(“;”);;
//将“IEnumerable textLines”转换回不带注释的字符串
string textWithoutComments=string.Join(“\n”,textLines);
//检索定义了哪些变量
//>>蓝色16711680
//>>红色255
Dictionary definedVariables=textLines.Where(line=>line.StartsWith(@“#define”))
.Select(line=>Regex.Match(line,@“#define([^]*)(.*)))
.ToDictionary(match=>match.Groups[1]。值,match=>match.Groups[2]。值);
//创建已定义节的字典
//>>设置文件名
//>>文件说明
//>>v1.0
// >>
//>>蓝色部分N033.56.09.699 W118.25.09.714
// >>
//>>第2节红色N033.56.13.675 W118.24.30.908
//>>N033.56.13.675 W118.24.30.908
//>>N033.56.16.034 W118.24.07.905
Dictionary sectionDictionary=Regex.Matches(无注释的文本,@“\[([\w]*)\]\n([^\[^\\\\\\\]*))
.Cast()
.ToDictionary(match=>match.Groups[1]。值,match=>match.Groups[2]。值);
UserConfiguration userConfig=新的UserConfiguration
{
变量=定义的变量,
设置=sectionDictionary[“设置”],
Sections=sectionDictionary.Where(dictionary=>dictionary.Key!=“设置”)
.Select(dictionary=>new{Key=dictionary.Key,Value=Regex.Match(dictionary.Value,@“(\w*)([^\[]*)”)
.ToDictionary(anon=>anon.Key,anon=>new Config