2012-11-28 11 views
5

Robię parsowanie xml i robię ciąg znaków replaceAll, który używa ogromnej ilości miejsca w pamięci, jak pokazano na poniższym obrazie.Zastąp ciąg przy użyciu ogromnej przestrzeni sterty

Kod wygląda tak:

private final String getText() { 
    // special handling for apostrophe encoding 
    // site will expect both ' , ' and %27. 
    // change %27 or 'or ' to ' 
    return _text.toString().trim().replaceAll("'", "'") 
      .replaceAll("'", "'").replaceAll("%27", "'"); 
} 

Sposób getText() często dzwonić z endElement() metody SAXParser.

Może ktoś sugerują, w jaki sposób zmienić tę funkcjonalność, która będzie używać mniej miejsca sterty

! [Śladu] [1]

+0

masz do czynienia z ogromnymi węzłów tekstu w xml? – jtahlborn

Odpowiedz

3

Używanie wyrażeń regularnych do prostego zastępowania ciągów w ten sposób jest zbyt kosztowne. Chciałbym po prostu budować instancji StringBuilder takiego:

StringBuilder sb = new StringBuilder(); 

while (not end of _text) { 
    find next '&' 
    if the next substring is in (' ') etc. 
    append the prev portion of _text to sb 
    append replacement char 
    set the beginning of the chunk to the next char 
} 
return sb.toString(); 
1

Twoja metoda replaceAll nazywa na String, która jest niezmienna. Z tego powodu za każdym razem, gdy je modyfikujesz, należy utworzyć cały nowy ciąg (w tym przypadku trzykrotnie). Jeśli zamiast tego użyjesz StringBuilder, twój ciąg będzie zmienny i nie będzie musiał być ponownie przydzielany za każdym razem, gdy coś zmienisz.

Nawiasem mówiąc, nie ma "zamieniać", jak potrzebujesz w StringBuilders, więc będziesz musiał wielokrotnie używać indexOf, aby znaleźć swój obraźliwy ciąg i replace na temat ustaleń. trim() tam jest.

3

Od _text jest już StringBuffer można użyć indexOf(String str) i replace(int start, int end, String str). W ten sposób nie utworzysz żadnych tymczasowych obiektów.

Korzystanie z funkcji takich jak:

private void replace(StringBuffer buff,String toReplace,String replaceTo){ 
int start; 
while ((start=buff.indexOf(toReplace))>=0) 
    buff.replace(start,start+toReplace.length(),replaceTo); 
} 

i wywołać funkcję w ciebie getText(), dla każdej kombinacji, jak:

String replaceTo=","; 
replace(_text,"'",replaceTo); 
replace(_text,"'",replaceTo); 
replace(_text,"%27",replaceTo); 
return _text.toString(); 
+0

Dokładnie to, czego potrzebowałem. Dziękuję Ci. –

1

Można zrobić wszystkie 3 zastępstwo za jednym zamachem jak

text.replaceAll("('|&39;|%27)", "'"); 

jest do 3 razy bardziej wydajne niż 3 kolejne zamienniki, ponieważ każdy zastąpić może utworzyć nowy ciąg

1

Ponieważ jesteś zaczyna swój tekst w SAX musi pochodzić stąd

characters(char[] ch, int start, int length) 

trzeba zapisać te args w polach i na endElement() można wykonać wymianę jak

StringBuilder sb = new StringBuilder(); 
    for (int i = start; i < length; i++) { 
       // %27 
     if (ch[i] == '%' && length - i > 2 && ch[i + 1] == '2' && ch[i + 2] == '7') { 
         sb.append('\''); 
      i += 2; 
       // &apos; 
       } else if (
        ... 
       // &#39; 
       } else if (
        ... 
     } else { 
      sb.append(ch[i]); 
     } 
    } 
    String res = sb.toString(); 

kod jest długi, ale bardzo skuteczny, można również dodać przycinanie

Powiązane problemy