C#中文本文件解析的最佳方法?

时间:2008-08-17 22:02:31

标签: c# fileparse

我想解析配置文件sorta的事情,如下:

[KEY:Value]     
    [SUBKEY:SubValue]

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

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

8 个答案:

答案 0 :(得分: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# library here,我没有亲自使用过,但是yaml非常简单,所以“它有多难?” : - )

我认为最好发明自己的ad-hoc格式(并处理解析器错误)

答案 1 :(得分:4)

前几天我几乎看到了这个确切的问题:关于字符串标记化的this article正是你所需要的。您需要将令牌定义为:

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

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

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

注意:文章缺少|在其示例中的字符,只需将它们扔进去。

答案 2 :(得分:1)

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

答案 3 :(得分:1)

使用库几乎总是最好自己动手。这是一个快速列表,“哦,我永远不需要那个/我没有考虑到这一点”,这些点最终会让你在以后咬你:

  • 转义字符。如果你想要一个:在键中的值或者在值中怎么样?
  • 逃离逃脱角色。
  • 的Unicode
  • 标签和空格的混合(请参阅Python的空格敏感语法的问题)
  • 处理不同的返回字符格式
  • 处理语法错误报告

像其他人所说,YAML看起来是你最好的选择。

答案 4 :(得分:0)

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

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

然后是的,那里有一个很好的方法。

答案 5 :(得分: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";
    }

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

答案 6 :(得分: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, ']');
}

答案 7 :(得分:-1)

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

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

这两个可以获得第一组中的Value和SubValue。查看MSDN如何将正则表达式与字符串匹配。

这是每个人都应该拥有的小猫。前正规革命时期似乎是冰河时代。