【发布时间】:2010-11-03 08:58:11
【问题描述】:
我有以下日志文件:
START:SOME_STRING
BL:2
LK:3
LH:5
end
START:SOME_STRING
BL:5
LK:6
LH:6
end
里面有多个 START: -> end 结构。有没有更好的“不马虎”方式来解析这个文件,而不是逐行读取并使用 SPLIT?
【问题讨论】:
标签: c# text-parsing
我有以下日志文件:
START:SOME_STRING
BL:2
LK:3
LH:5
end
START:SOME_STRING
BL:5
LK:6
LH:6
end
里面有多个 START: -> end 结构。有没有更好的“不马虎”方式来解析这个文件,而不是逐行读取并使用 SPLIT?
【问题讨论】:
标签: c# text-parsing
您可以尝试形式化您的 ini 文件的语法,以及一些解析器生成器。详情请参阅this question。
请注意,对于像您这样简单的语法,手动解析可能更容易:-P
class IniEntry
{
public int BL;
public int LK;
public int LH;
IniEntry Clone() { return new IniEntry { BL = BL, LK = LK, LH = LH }; }
}
IEnumerable<IniEntry> Parse()
{
IniEntry ie = new IniEntry();
while (ParseEntry(out ie))
yield return ie.Clone();
}
bool ParseEntry(out IniEntry ie)
{
ie = new IniEntry();
return ParseStart(ie) &&
ParseBL(ie) &&
ParseLK(ie) &&
ParseLH(ie) &&
ParseEnd(ie);
}
bool ParseStart(IniEntry ie)
{
string dummy;
return ParseLine("START", out dummy);
}
bool ParseBL(IniEntry ie)
{
string BL;
return ParseLine("BL", out BL) && int.TryParse(BL, out ie.BL);
}
bool ParseLK(IniEntry ie)
{
string LK;
return ParseLine("LK", out LK) && int.TryParse(LK, out ie.LK);
}
bool ParseLH(IniEntry ie)
{
string LH;
return ParseLine("LH", out LH) && string.TryParse(LH, out ie.LH);
}
bool ParseLine(string key, out string value)
{
string line = GetNextLine();
var parts = line.Split(":");
if (parts.Count != 2) return false;
if (parts[0] != key) return false;
value = parts[1];
}
等等
【讨论】:
这是 while 循环和状态机的理想选择。 使用这种方法,您甚至可以使用更少的内存并比使用 string.split() 具有更高的性能
【讨论】:
如果确定 START/END 总是匹配的,(抱歉,我的 C# 很尴尬,这么简单的英文):
Read the whole file with System.IO.ReadToEnd
Parse the whole thing in one go with a regular expression
Iterate over regex results
正则表达式类似于“(START:([^$]+)$BL:([^$]+)$LK:([^$]+)$LH:([^$]+) $end$)+",在我的脑海中,你需要根据你的参数 BL/LK 等如何发生来验证/调整
【讨论】: