【问题标题】:Best method of Textfile Parsing in C#?C#中文本文件解析的最佳方法?
【发布时间】:2010-09-06 01:13:39
【问题描述】:

我想解析一个配置文件,就像这样:

[KEY:Value]     
    [SUBKEY:SubValue]

现在我从StreamReader 开始,将行转换为字符数组,当时我认为必须有更好的方法。所以我请求你,谦虚的读者,帮助我。

一个限制是它必须在 Linux/Mono 环境中工作(准确地说是 1.2.6)。我没有最新的 2.0 版本(Mono),因此请尝试将语言功能限制为 C# 2.0 或 C# 1.0。

【问题讨论】:

    标签: c# fileparse


    【解决方案1】:

    我考虑过,但我不会使用 XML。我将手动编写这些东西,而手动编辑 XML 让我很头疼。 :')

    你看过YAML吗?

    您可以从 XML 中受益,而无需承受所有的痛苦。它在 ruby​​ 社区中被广泛用于配置文件、预先准备好的数据库数据等方面

    这是一个例子

    customer:
      name: Orion
      age: 26
      addresses:
        - type: Work
          number: 12
          street: Bob Street
        - type: Home
          number: 15
          street: Secret Road
    

    好像有个C# library here,我个人没用过,不过yaml挺简单的,所以“能有多难?” :-)

    我想说这比发明自己的临时格式(并处理解析器错误)更可取

    【讨论】:

      【解决方案2】:

      前几天我几乎正在研究这个确切的问题:this article 字符串标记正是您所需要的。您需要将令牌定义为:

      @"(?&ltlevel>\s) | " +
      @"(?&ltterm>[^:\s]) | " +
      @"(?&ltseparator>:)"
      

      这篇文章很好地解释了它。从那里你开始吃你认为合适的代币。

      Protip:对于LL(1) parser(阅读:简单),令牌不能共享前缀。如果你有abc 作为令牌,你不能有ace 作为令牌

      注意:文章缺少 |示例中的字符,只需将它们放入即可。

      【讨论】:

        【解决方案3】:

        another YAML library for .NET 正在开发中。目前它支持读取 YAML 流,并且已经在 Windows 和 Mono 上进行了测试。目前正在实施写入支持。

        【讨论】:

          【解决方案4】:

          使用库几乎总是比使用自己的库更好。以下是“哦,我永远不需要那个/我没想到那个”点的快速列表,这些点最终会在以后咬你:

          • 转义字符。如果您希望键中的 : 或值中的 ] 怎么办?
          • 转义转义字符。
          • Unicode
          • 制表符和空格的混合(请参阅 Python 的空格敏感语法问题)
          • 处理不同的返回字符格式
          • 处理语法错误报告

          就像其他人建议的那样,YAML 看起来是您的最佳选择。

          【讨论】:

            【解决方案5】:

            您还可以使用堆栈,并使用推送/弹出算法。这个匹配打开/关闭标签。

            public string check()
                {
                    ArrayList tags = getTags();
            
            
                    int stackSize = tags.Count;
            
                    Stack stack = new Stack(stackSize);
            
                    foreach (string tag in tags)
                    {
                        if (!tag.Contains('/'))
                        {
                            stack.push(tag);
                        }
                        else
                        {
                            if (!stack.isEmpty())
                            {
                                string startTag = stack.pop();
                                startTag = startTag.Substring(1, startTag.Length - 1);
                                string endTag = tag.Substring(2, tag.Length - 2);
                                if (!startTag.Equals(endTag))
                                {
                                    return "Fout: geen matchende eindtag";
                                }
                            }
                            else
                            {
                                return "Fout: geen matchende openeningstag";
                            }
                        }
                    }
            
                    if (!stack.isEmpty())
                    {
                        return "Fout: geen matchende eindtag";
                    }            
                    return "Xml is valid";
                }
            

            您可能可以进行调整,以便阅读文件的内容。正则表达式也是一个好主意。

            【讨论】:

              【解决方案6】:

              在我看来,您最好使用基于 XML 的配置文件,因为已经有 .NET 类可以相对轻松地为您读取和存储信息。这是不可能的吗?

              @Bernard:手动编辑 XML 确实很乏味,但您呈现的结构已经看起来与 XML 非常相似。

              那么是的,那里有一个好方法。

              【讨论】:

                【解决方案7】:

                @Gishu

                实际上,一旦我适应了转义字符,我的正则表达式的运行速度比我手写的自上而下递归解析器稍慢,而且没有嵌套(将子项链接到它们的父项)和错误报告手写解析器。

                正则表达式的编写速度稍快一些(尽管我确实有一些手动解析器的经验),但这并没有很好的错误报告。一旦你添加它,它就会变得稍微困难​​和更长。

                我还发现手写解析器更容易理解其意图。例如,这里是一个 sn-p 的代码:

                private static Node ParseNode(TextReader reader)
                {
                    Node node = new Node();
                    int indentation = ParseWhitespace(reader);
                    Expect(reader, '[');
                    node.Key = ParseTerminatedString(reader, ':');
                    node.Value = ParseTerminatedString(reader, ']');
                }
                

                【讨论】:

                  【解决方案8】:

                  不管持久化格式如何,使用正则表达式都是最快的解析方式。 在 ruby​​ 中,它可能是几行代码。

                  \[KEY:(.*)\] 
                  \[SUBKEY:(.*)\]
                  

                  这两个将为您提供第一组中的 Value 和 SubValue。查看 MSDN,了解如何将正则表达式与字符串匹配。

                  这是每个人都应该在他们的小猫身上拥有的东西。正则表达式之前的日子看起来就像冰河时代。

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 2011-04-29
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2011-12-18
                    • 2018-07-27
                    相关资源
                    最近更新 更多