2010-04-06 225 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);