2008-08-17 38 views
9

我想分析一个配置文件八九不离十的事情,就像这样:C#中文本文件解析的最佳方法?

[KEY:Value]  
    [SUBKEY:SubValue] 

现在我开始用StreamReader,转换线入字符数组,当我想通有一定有一个更好的办法。所以我请你,谦虚的读者来帮助我。

一个限制是它必须在Linux/Mono环境下工作(准确的说是1.2.6)。我没有最新的2.0版本(单声道),所以尝试将语言功能限制为C#2.0或C#1.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格式(与解析器错误处理)

0

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

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

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

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

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

4

我几天就在看这个确切的问题:this article关于字符串标记化正是你所需要的。您需要将您的令牌定义为如下形式:

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

本文对解释它做了很好的工作。从那里开始,只要你认为合适,就开始吃掉代币。

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

注意:文章缺少|在它的例子中的字符,只是把它们扔进去。

1

使用图书馆几乎总是最好滚动你自己的。这里有一个快速列表“哦,我永远不会需要一个/我没有想到的是”点,这最终会来咬你以后的路线:

  • 转义字符,如果你所想:密钥或]中的值?
  • 转义转义字符
  • Unicode的
  • 制表符和空格的混合(见与Python的空格敏感的语法问题)
  • 处理不同的返回字符格式
  • 处理语法错误报告

像其他人建议,YAML看起来像你的最好的选择。

-1

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

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

这两个会让你在第一组中的Value和SubValue。查看MSDN如何针对字符串匹配正则表达式。

这是每个人都应该在他们的小猫。 Pre-Regex日子看起来像冰河时代。

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, ']'); 
} 
1

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

相关问题