【问题标题】:Best way to parse a log file in C#在 C# 中解析日志文件的最佳方法
【发布时间】: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


    【解决方案1】:

    您可以尝试形式化您的 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];
    }
    

    等等

    【讨论】:

    • 这就是我要解析的日志文件,很遗憾不会更改。
    • 你不需要更改日志文件,为什么?
    【解决方案2】:

    这是 while 循环和状态机的理想选择。 使用这种方法,您甚至可以使用更少的内存并比使用 string.split() 具有更高的性能

    【讨论】:

    • 一些关于状态机的更多细节会得到我的支持。
    • 状态机?我去看看。
    • 避免做事过于“马虎”的陷阱。除非您可以重用一些其他状态机实现,否则如果可以的话,您最好两次。您可以在更短的时间内完成 SPLIT 选项。
    【解决方案3】:

    如果确定 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 等如何发生来验证/调整

    【讨论】:

    • 当我需要读取的某些文件超过 6000 行时,这听起来效率不高。除非我弄错了?
    • 这真是一个糟糕的解决方案。想象一下这个文件有几百兆的大小。最好逐行(或逐块)阅读并使用某种状态机。
    • 内存真的有问题吗?即使它暂时占用 1Gb 的内存,那又如何呢?当然,状态机更优雅,但这很快解决了问题
    猜你喜欢
    • 1970-01-01
    • 2022-06-23
    • 2011-04-29
    • 2012-05-01
    • 1970-01-01
    • 2010-09-06
    • 1970-01-01
    • 1970-01-01
    • 2010-09-06
    相关资源
    最近更新 更多