9

我想解析一个配置文件排序的东西,像这样:

[KEY:Value]     
    [SUBKEY:SubValue]

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

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

4

8 回答 8

12

我考虑过,但我不会使用 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# 库,我没有亲自使用过,但是 yaml 很简单,所以“它有多难?” :-)

我会说最好发明自己的临时格式(并处理解析器错误)

于 2008-08-17T22:39:50.833 回答
4

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

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

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

Protip:对于LL(1) 解析器(阅读:easy),标记不能共享前缀。如果你有abc作为令牌,你就不能ace作为令牌

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

于 2008-08-17T22:25:55.433 回答
1

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

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

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

于 2008-08-18T00:35:36.310 回答
1

There is another YAML library for .NET which is under development. Right now it supports reading YAML streams and has been tested on Windows and Mono. Write support is currently being implemented.

于 2008-08-26T23:33:36.833 回答
0

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

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

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

于 2008-08-17T22:12:15.740 回答
0

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

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";
    }

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

于 2008-08-17T22:12:19.267 回答
0

@Gishu

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

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

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

private static Node ParseNode(TextReader reader)
{
    Node node = new Node();
    int indentation = ParseWhitespace(reader);
    Expect(reader, '[');
    node.Key = ParseTerminatedString(reader, ':');
    node.Value = ParseTerminatedString(reader, ']');
}
于 2008-08-18T07:52:29.237 回答
-1

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

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

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

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

于 2008-08-18T07:22:11.950 回答