2008-08-17 76 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上進行了測試。寫支持目前正在實施中。

相關問題