Java escape HTML - строка заменяет медленно? - PullRequest
2 голосов
/ 06 апреля 2010

У меня есть Java-приложение, которое интенсивно использует большой файл для чтения, обработки и передачи в SolrEmbeddedServer (http://lucene.apache.org/solr/).

Одна из функций выполняет обычное экранирование HTML:

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

При профилировании приложения программа тратит примерно 58% времени на выполнение этой функции, 47% заменяет и 11% заменяет все.

Теперь, Java заменяет это медленно или я на правильном пути, и я должен считать программу достаточно эффективной, чтобы иметь узкое место в Java, а не в моем коде? (Или я заменяю неправильно?)

Заранее спасибо!

Ответы [ 8 ]

8 голосов
/ 06 апреля 2010

Для выхода из html вы можете использовать StringEscapeUtils.escapeHtml(input) из commons-lang . Там якобы он реализован более эффективно.

3 голосов
/ 06 апреля 2010

Это, конечно, не самый эффективный способ сделать много замен. Поскольку строки неизменяемы, каждый .replace () приводит к созданию нового объекта String. В приведенном вами примере каждый вызов этой функции приводит к временному созданию 6 объектов String.

Учитывая приведенный вами пример, самое простое решение - использовать существующую библиотечную функцию для кодирования сущностей HTML. Apache commons StringEscapeUtils является одним из вариантов. Еще один - HTMLEntities

1 голос
/ 04 марта 2011

Гораздо проще и стандартнее в использовании http://commons.apache.org/lang/. Это очень легко и просто.

1 голос
/ 06 апреля 2010

Каждый вызов на замену возвращает новую строку. Каждый раз, когда вы вызываете эту функцию, вы, по сути, создаете четыре копии строк, которые будут немедленно удалены. Если ввод достаточно велик, это может быть расточительным.

Я бы предложил пересмотреть ваш алгоритм, чтобы вместо выполнения операций 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();
}
1 голос
/ 06 апреля 2010

Apache Commons Lang имеет очень эффективный метод escapeHtml в своем классе StringEscapeUtils.

Это довольно умно, и он не использует замену строк в том виде, как вы описываете, но вместо этого перебирает символы, заменяя символы соответствующими объектами, когда находит их.

У меня нет удобных тестов, но если этот материал находится на критическом пути вашего кода, было бы разумно использовать это готовое, более быстрое решение.

0 голосов
/ 14 июля 2014

Для случайного читателя в Html escape-поле появился новый игрок: unbescape .

Операция unescape над кодом HTML может быть выполнена следующим образом:

final String unescapedText = HtmlEscape.unescapeHtml(escapedText); 
0 голосов
/ 06 апреля 2010

Общий алгоритм для String.replace немного сложен, но он не должен быть таким плохим.Глядя на код, он на самом деле реализован с использованием регулярных выражений, поэтому не будет быстрым - ick.

Очевидно, что вы можете писать гораздо более быстрый код, перебирая символ за символом.Возможно, сначала определите точную длину.

Возможно, вы захотите рассмотреть, как обрабатываются символы за пределами [ -~].Вы также можете использовать библиотеку, в которой уже реализована эта функциональность.

0 голосов
/ 06 апреля 2010

Ваш подход с несколькими методами замены может быть медленным.

Посмотрите на Apache Commons Lang StringEscapeUtils для быстрой реализации экранирования сущностей HTML.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...