2008-08-21 25 views
13

我有一個大型文本模板,需要用其他文本替換標記化部分。令牌看起來像這樣:## USERNAME ##。我的第一個直覺就是使用String.Replace(),但有沒有更好,更有效的方法,或者是已經爲此優化的Replace()?在大型文本模板中替換標記的最佳方法

回答

12

System.Text.RegularExpressions.Regex.Replace()是你所尋求的 - 如果你的令牌足夠奇怪,你需要一個正則表達式來找到它們。

Some kind soul did some performance testing以及Regex.Replace(),String.Replace()和StringBuilder.Replace()之間,String.Replace()實際上排在最前面。

+1

我相信他們在PowerShell中做了不適用於C#的測試。 C3與PowerShell有不同的內存管理,並且不會將StringBuilder轉換爲字符串來替換它中的字符。另一方面,正則表達式和StringBuilder在大塊數據上更好地工作 – AaA 2013-04-24 07:38:49

+0

RegEx是對大量文本進行替換的可怕選項。儘管功能強大,許多RegEx支持者將整個世界視爲釘子和RegEx作爲他們的錘子。對於涉及大量文本的用例,請看FastReplacer http://stackoverflow.com/a/11442008/141172 – 2014-11-05 17:57:05

2

string.Replace很好。我更喜歡使用正則表達式,但我是***正則表達式。

要記住的是這些模板有多大。如果它真的很大,並且內存是一個問題,那麼您可能需要創建一個自定義標記器來處理流。這樣,在操作它時,只能將文件的一小部分保存在內存中。

但是,對於耐心的實現,string.Replace應該沒問題。

2

如果您在大型字符串上進行多次替換,那麼最好使用StringBuilder.Replace(),因爲字符串通常會出現性能問題。

2

不得不近期做類似的事情。我所做的是:

  • 做,需要一個字典的方法(鍵=標記名稱,值=你需要插入文本)
  • 獲取所有你的令牌格式(##場比賽+#? #在你的情況下,我猜想,在正則表達式中不是那麼好:P)使用Regex.Matches(輸入,正則表達式)
  • foreach結果,使用字典爲你的標記查找插入值。
  • 返回結果。

做;-)

如果你想測試你的正則表達式我可以建議the regulator.

7

我不得不這樣做的唯一情況是發送一個模板化的電子郵件。在.NET中,開箱即用MailDefinition class提供。因此,這是你如何創建一個模板消息:

MailDefinition md = new MailDefinition(); 
md.BodyFileName = pathToTemplate; 
md.From = "[email protected]"; 

ListDictionary replacements = new ListDictionary(); 
replacements.Add("<%To%>", someValue); 
// continue adding replacements 

MailMessage msg = md.CreateMailMessage("[email protected]", replacements, this); 

在此之後,msg.Body將通過模板替換值創建。我想你可以看看MailDefinition.CreateMailMessage()與反射器:)。對不起,有點偏離主題,但如果這是你的情況,我認爲這是最簡單的方法。

2

正則表達式是最快的代碼解決方案,但如果你有許多不同的令牌,那麼它會變慢。如果性能不是問題,則使用此選項。

更好的方法是定義令牌,就像您可以在文本中掃描的「##」一樣。然後選擇要使用以令牌作爲關鍵字的文本從散列表中替換的內容。

如果這是構建腳本的一部分,那麼nAnt有一個很好的功能來做這個叫做Filter Chains。這個代碼是開源的,所以你可以看看它是如何完成的快速實現。

3

那麼,取決於你在模板中有多少變量,你有多少模板等,這可能是一個完整的模板處理器的工作。我曾經用過.NET的唯一一個是NVelocity,但我確定其中必須有其他許多人,其中大部分都與某些Web框架或其他框架相關聯。

1

如果你的模板很大,並且你有很多標記,你可能不想走它並逐個替換模板中的標記,因爲這會導致O(N * M)操作,其中N是模板的大小和M是要替換的令牌的數量。

以下方法接受您希望替換的鍵值對的模板和字典。通過將StringBuilder初始化爲略大於模板的大小,它應該導致O(N)操作(即它不應該自己增長日誌N次)。

最後,您可以將令牌的構建移動到單例中,因爲它只需要生成一次。

static string SimpleTemplate(string template, Dictionary<string, string> replacements) 
{ 
    // parse the message into an array of tokens 
    Regex regex = new Regex("(##[^#]+##)"); 
    string[] tokens = regex.Split(template); 

    // the new message from the tokens 
    var sb = new StringBuilder((int)((double)template.Length * 1.1)); 
    foreach (string token in tokens) 
     sb.Append(replacements.ContainsKey(token) ? replacements[token] : token); 

    return sb.ToString(); 
} 
2

FastReplacer實現爲O令牌替換(N *的log(n)+ m)個時間,並使用3倍原始字符串的存儲器中。

當性能很重要時,FastReplacer適用於對大字符串執行許多Replace操作。

主要思想是避免每次更換字符串時修改現有文本或分配新內存。

我們設計了FastReplacer來幫助我們完成一個項目,在這個項目中,我們必須生成一個大量文本,並附加大量的附加和替換操作。使用StringBuilder生成文本的第一個版本的應用程序需要20秒。使用String類的第二個改進版本花了10秒鐘。然後我們實現了FastReplacer,持續時間縮短到0.1秒。

相關問題