2017-01-17 2 views
0

Я имею список DTO, который преобразуется из ответа HTTP (используя RestTemplate вызов), имеющий два значения ID и содержание. Когда я итерация список, я вылетающих HTML символов DTO по своему содержанию и замены некоторых страшных символов, используя код ниже:Java постоянная строка слишком долго Исключение - Runtime

String content = null; 
    for(TestDto testDto: testDtoList) { 
     try { 
      content = StringEscapeUtils.unescapeHtml4(testDto.getContent()). 
             replaceAll("<style(.+?)</style>", ""). 
             replaceAll("<script(.+?)</script>", ""). 
             replaceAll("(?s)<[^>]*>(\\s*<[^>]*>)*", " "). 
             replaceAll("[^a-zA-Z0-9\\\\.]+", " "). 
             replace("\\n", " "). 
             replaceAll("\\\\r","").trim(); 
      processContent(content); 
     } catch (Exception e) { 
      System.out.println("Content err: " + e.getMessage()); 
     } 
    } 

Между цикла, код получить остановлен из-Java постоянная строка слишком долго исключение. Даже я не могу поймать это исключение. Как мне решить эту проблему?

EDIT:

Длина getContent() строки может превышает Integer.MAX_VALUE

+0

Возможно, попробуйте использовать 'org.apache.commons.lang.StringUtils.join'? – Idos

+2

Возможный дубликат [Java "константа строка слишком длинная" компилировать ошибку. Только происходит с использованием Ant, а не при использовании Eclipse] (http://stackoverflow.com/questions/2738574/java-constant-string-too-long-compile-error-only-happens-using-ant-not-when).Не думайте, что это связано с Ant – AxelH

+0

@AxelH Нет, это не связано с Ant – RGG

ответ

0

Этот код трудно читать в любом случае, так что вы можете захотеть, чтобы реорганизовать его. Одна вещь, которую вы могли бы попробовать, - использовать StringBuffer вместе с Pattern, Matcher и appendReplacement() и appendTail() методами. Таким образом, вы можете доказать список шаблонов и замен, перебрать его, перебрать все вхождения текущего шаблона и заменить его. К сожалению, эти методы не принимают StringBuilder, но, по крайней мере, стоит попробовать. Фактически, метод replaceAll() в основном делает то же самое, но, делая это самостоятельно, вы можете пропустить часть return sb.toString();, которая, вероятно, вызывает проблему.

Пример:

class ReplacementInfo { 
    String pattern; 
    String replacement; 
} 

List<ReplacementInfo> list = ...; //build it 

StringBuffer input = new StringBuffer(testDto.getContent()); 
StringBuffer output = new StringBuffer(); 

for(ReplacementInfo replacementInfo : list) { 
    //create the pattern and matcher for the current input 
    Pattern pattern = Pattern.compile(replacementInfo.pattern); 
    Matcher matcher = pattern.matcher(input); 

    //replace all occurences of the pattern 
    while(matcher.find()) { 
    matcher.appendReplacement(output, replacementInfo.replacement); 
    } 
    //add the rest of the input 
    matcher.appendTail(output); 

    //reuse the output as the input for the next iteration 
    input = output; 
    output = new StringBuffer(); 
} 

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

Btw, вы также можете посмотреть в использовании StringEscapeUtils.UNESCAPE_HTML4.translate(input, writer) вместе с StringWriter, что позволяет получить доступ к основному StringBuffer и, таким образом, полностью работать на содержание без использования String.

+0

Ницца общей логики. Но исправьте меня, если я ошибаюсь, но результирующая строка будет такой же. Таким образом, это тоже не поместится в String. Правильно ? – AxelH

+0

@AxelH, что может быть так, но это зависит от того, что 'testDto.getContent()' и что вам нужно. приведенный выше код позволит вам не использовать строки вообще, а работать только с экземплярами «CharacterSequence». Это также зависит от того, где именно вы получаете это исключение, потому что фактическая проблема может быть чем-то еще. – Thomas

+0

Но если я не ошибаюсь, исключение должно происходить, потому что длина больше, чем 'Integer.MAX_VALUE', предел String, а также предел массивов. Поскольку 'Charsequence' использует' charAt (int) ', это может быть и ограничение. (только гадать;)) – AxelH

0

Измени поймать блок, как показано ниже,

String content = null; 
    for(TestDto testDto: testDtoList) { 
     try { 
      content = StringEscapeUtils.unescapeHtml4(testDto.getContent()). 
            replaceAll("<style(.+?)</style>", ""). 
            replaceAll("<script(.+?)</script>", ""). 
            replaceAll("(?s)<[^>]*>(\\s*<[^>]*>)*", " "). 
            replaceAll("[^a-zA-Z0-9\\\\.]+", " "). 
            replace("\\n", " "). 
            replaceAll("\\\\r","").trim(); 
     } catch (ContentTooLongException e) { 
      System.out.println("Content err: " + e.getMessage()); 
     }catch (Exception e) { 
      System.out.println("other err: " + e.getMessage()); 
     } 
    } 

Теперь вы будете иметь возможность обрабатывать любое исключение.

+0

Ловля исключения никогда не должна быть решением. Особенно, если ничего не сделать, чтобы справиться с этим. – AxelH

+0

На самом деле его трудно определить проблему, не зная фактического ответа. Может быть, это связано с какой-то проблемой кодирования символов или чем-то еще. По крайней мере, после обработки проблемы мы можем позаботиться об ответе в соответствии с требованиями, а не бросать исключение на сервер. –

+0

См. [Неправильная практика ловить Throwable?] (Http://stackoverflow.com/q/6083248/4391450). – AxelH

0

Предположив ваш DTO не является достаточно большим, вы можете:

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

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