我需要一些帮助来解析包含多个部分的文本文件。该文件采用以下格式:
;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]"))
{
}
}
}
答案 0 :(得分:3)
如果这是您想要的数据结构类型,您可以使用以下代码....
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";
答案 1 :(得分:0)
不想测试它,但这是一个开始:
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]"))
{
}
}
答案 2 :(得分:0)
我在字典中创建了不同的操作以允许可读性 - 当您开始添加部分时,if
语句将变成可维护性的噩梦。我使用控制台进行了测试,所以这在代码方面有点粗糙。简而言之:
查看记录是否为#definition
记录,如果是,则将其拆分为名称和值字符串集。
如果记录是代码注释记录,请跳过。
如果记录以字典键中的任何内容开头,请将当前部分更新为该字段。因此,当您看到[Settings]
时,当前操作将为UpdateSettingsConfiguration
,当您看到[Section]
时,当前操作将为UpdateSectionConfiguration
。
当记录不是注释,#definition
记录或节标题时,它将调用应用于最近定义的节标题的Action并允许其处理。如果用户顽皮并在文件中的多个位置定义[Settings]
,这也很方便。
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
}
}