2010-04-06 209 views
2

我有一個Java應用程序,它大量使用一個大文件,讀取,處理並傳遞給SolrEmbeddedServer(http://lucene.apache.org/solr/)。Java轉義HTML - 字符串替換慢?

上述功能之一確實基本的HTML轉義:

private String htmlEscape(String input) 
{ 
    return input.replace("&", "&amp;").replace(">", "&gt;").replace("<", "&lt;") 
     .replace("'", "&apos;").replaceAll("\"", "&quot;"); 
} 

雖然分析應用程序,該程序花費的時間大約58%在此函數中,總的47%替換,並且在11%的全部替換。

現在,Java替換是否緩慢,還是我在正確的道路上,我應該認爲該程序是否足夠有效,在Java中而不是在我的代碼中存在瓶頸? (或者我更換錯了?)

在此先感謝!

回答

8

對於html轉義,您可以使用commons-lang中的StringEscapeUtils.escapeHtml(input)。據推測,這是以更有效的方式實施的。

+1

我建議複製這種一個方法,而不是公共琅(你可以做到這一點,因爲在法律上它ASF2.0行貨),除非你需要commons-lang提供的其他方法和輔助類。對單一方法有一個全新的依賴是不好的。 – Esko 2010-04-06 13:21:47

+0

是的,但commons-lang有很多方法可能在大多數應用程序中很有用,他們的作者重寫它們,但不知道它們存在。 – Bozho 2010-04-06 13:24:06

+0

謝謝,這可能會有用。如果我沒有弄錯,該項目已經使用apache commons作爲Solr的依賴項。我會研究它:) – cpf 2010-04-06 17:12:23

3

這當然不是做大量替換的最有效方法。由於字符串是不可變的,每個.replace()都會導致構建一個新的String對象。對於您提供的示例,每次調用此函數都會導致臨時創建6個String對象。

考慮到您給出的示例,最簡單的解決方案是使用現有的庫函數進行HTML實體編碼。阿帕奇公用StringEscapeUtils是一種選擇。另一個是HTMLEntities

1

Apache Commons Lang在其StringEscapeUtils類中有一個非常有效的escapeHtml方法。

它相當聰明,不會按照您描述的方式使用字符串替換,而是遍歷字符,在找到它們時用適當的實體替換字符。

我沒有任何基準方便,但如果這些東西在代碼的關鍵路徑上,那麼使用這個現成的,更快的解決方案將會很有用。

0

String.replace的一般算法有點複雜,但它不應該那麼糟糕。看代碼,它實際上是使用正則表達式實現的,所以不會很快 - ick。

顯然,您可以通過逐個字符地遍歷來編寫更快的代碼。可能首先確定確切的長度。

您可能想要考慮如何處理[ -~]以外的字符。您可能還想使用已實現該功能的庫。

1

每次調用replace都會返回一個新的String。每次調用這個函數時,你都會創建四個將被立即丟棄的字符串。如果輸入足夠大,這可能是浪費。

我建議修改你的算法,這樣,而不是進行N replace操作(這需要每次掃描字符串),你只掃描列表一次:

//psuedocode 
Map<Char, String> replacements = new HashMap<String, String>(); 
replacements.put("&", "&amp;"); 
replacements.put(">", "&gt;"); 
... 
private String htmlEscape(String input) { 
    StringBuilder sb = new StringBuilder(input.length()); 
    for (char c: sb.toCharArray()) { 
    if (replacements.containsKey(c)) { 
     sb.append(replacements.get(c)); 
    else { 
     sb.append(c); 
    } 
    return sb.toString(); 
} 
+0

我已經改變了我的實現來檢查某個字符是否在字符串中,希望如果更快然後就這麼做......(還沒有結果,但我可能會按照其他人的建議使用StringEscapeUtils) – cpf 2010-04-06 17:11:09

0

對於休閒讀者,Html轉義字段中有一個新玩家:unbescape

對HTML代碼的UNESCAPE操作可以做這樣的:

final String unescapedText = HtmlEscape.unescapeHtml(escapedText);