2009-08-05 13 views
51

Używając Java, chcę przejść przez linie tekstu i zastąpić wszystkie symbole ampersand (&) z odwołaniem do jednostki XML &.Jak zamienić znak w łańcuch w Javie?

Przeszukuję wiersze tekstu, a następnie każde słowo w tekście za pomocą klasy Scanner. Następnie używam CharacterIterator do iteracji wszystkich znaków słowa. Jak jednak mogę zamienić postać? Po pierwsze, Ciągi są obiektami niezmiennymi. Po drugie, chcę zastąpić znak (&) kilkoma znakami (amp&;). Jak mam się do tego podejść?

CharacterIterator it = new StringCharacterIterator(token); 
for(char ch = it.first(); ch != CharacterIterator.DONE; ch = it.next()) { 
     if(ch == '&') { 

     } 
} 

Odpowiedz

100

Zamiast tego spróbuj użyć String.replaceAll().

String my_new_str = my_str.replaceAll("&", "&"); 
+61

Uważaj replaceAll , ponieważ używa swojego pierwszego argumentu jako wyrażenia regularnego. To znaczy. "h.e.l.o.o" .replaceAll (".", ",") da ci ",,,,,,,,,"! W Javie 1.5 jest nowa metoda String.replace (CharSequence, CharSequence), która robi coś podobnego, ale nie interpretuje pierwszego argumentu jako wyrażenia regularnego. –

14
StringBuilder s = new StringBuilder(token.length()); 

CharacterIterator it = new StringCharacterIterator(token); 
for (char ch = it.first(); ch != CharacterIterator.DONE; ch = it.next()) { 
    switch (ch) { 
     case '&': 
      s.append("&"); 
      break; 
     case '<': 
      s.append("&lt;"); 
      break; 
     case '>': 
      s.append("&gt;"); 
      break; 
     default: 
      s.append(ch); 
      break; 
    } 
} 

token = s.toString(); 
+1

Nie powinieneś potrzebować StringBuffer w tym scenariuszu. –

+1

Użycie ciągu znaków spowodowałoby utworzenie tymczasowego obiektu String w iteracji. Nie jestem pewien, jaką alternatywę zaproponujesz. –

+0

string.replaceAll? – IRBMe

4

Wystarczy utworzyć ciąg, który zawiera wszystkie dane o których mowa, a następnie użyć String.replaceAll() jak poniżej.

String result = yourString.replaceAll("&", "&amp;"); 
+0

Jeśli dane są zbyt duże, utworzenie pojedynczego ciągu zawierającego wszystkie dane może być niekorzystne. Możemy również wykonać linię po linii. – Bhushan

+0

Używanie replaceAll w tym przypadku jest NIEPRAWIDŁOWE! Jeśli to możliwe, zawsze używaj opcji replace zamiast replaceAll. Jest bardziej wydajny i mniej podatny na błędy. –

0

Zobacz metodę this.

+0

Zwróć uwagę na typy parametrów do zamiany (char, char) - zastępuje jeden znak. – Amber

+0

Tak, tak, naprawione natychmiast po wysłaniu. – IRBMe

+0

Myślę, że musisz wgrać [1] na swoim linku, aby uzyskać go w telefoniefy ... może? –

0

Jeśli używasz Wiosna można po prostu zadzwonić HtmlUtils.htmlEscape(String input) który zajmie się „” do „& &” przekładu.

+0

Jest to ryzykowne, ponieważ w HTML zdefiniowano wiele innych jednostek niż czysty XML. –

1

Uciekające struny can be tricky - zwłaszcza jeśli chcesz wziąć pod uwagę kod Unicode. Przypuszczam, że XML jest jednym z prostszych formatów/języków, które można uciec, ale wciąż. Polecam przyjrzeć się klasie StringEscapeUtils w Apache Commons Lang i jej przydatnej metodzie escapeXml.

7

Możesz również sprawdzić, czy nie zastępujesz wystąpienia, które zostało już zastąpione. Możesz użyć wyrażenia regularnego z ujemnym uprzedzeniem, aby to zrobić.

Na przykład:

String str = "sdasdasa&amp;adas&dasdasa";
str = str.replaceAll("&(?!amp;)", "&amp;");

Spowodowałoby napisu "sdasdasa & adas & dasdasa".

Wzorzec regex "& (?! Amp;)" zasadniczo mówi: Dopasuj dowolne wystąpienie "&", po którym nie występuje "amp;".

82

Odpowiedź jest prosta:

token = token.replace("&", "&amp;"); 

Pomimo nazwy, w porównaniu do replaceAll wymienić robi się replaceAll, to po prostu nie użyć wyrażenia regularnego, który wydaje się być w porządku tutaj (zarówno od perspektywa wykonania i dobra praktyka - nie używaj wyrażeń regularnych przez przypadek, ponieważ mają one specjalne wymagania dotyczące charakteru, na które nie będziesz zwracać uwagi).

Odpowiedź Seana Brighta jest prawdopodobnie tak dobra, na jaką warto się zastanowić z perspektywy wydajności, jeśli nie ma dalszych wymagań dotyczących testów wydajności i wydajności, jeśli już wiesz, że ten kod jest gorącym punktem dla wydajności, jeśli to jest twoje pytanie pochodzi z. Z pewnością nie zasługuje na pochlebstwa. Po prostu użyj StringBuilder zamiast StringBuffer, chyba że potrzebujesz synchronizacji.

W związku z powyższym istnieje nieco głębszy potencjalny problem. Uciekające postacie są znanym problemem, do którego odnosi się wiele bibliotek. Możesz rozważyć zawijanie danych w sekcji CDATA w pliku XML lub możesz użyć biblioteki XML (w tym tej, która jest teraz dostępna w JDK), aby właściwie wygenerować kod XML (tak, aby obsłużył kodowanie).

Apache ma również escaping library jako część Commons Lang.

0
//I think this will work, you don't have to replace on the even, it's just an example. 

public void emphasize(String phrase, char ch) 
    { 
     char phraseArray[] = phrase.toCharArray(); 
     for(int i=0; i< phrase.length(); i++) 
     { 
      if(i%2==0)// even number 
      { 
       String value = Character.toString(phraseArray[i]); 
       value = value.replace(value,"*"); 
       phraseArray[i] = value.charAt(0); 
      } 
     } 
    } 
1

Spróbuj tego kodu. Możesz zamienić dowolną postać na inną postać. Tutaj próbowałem zastąpić literę 'a' z "-" znak dla struny give "abcdeaa"

Wyjście -> _ bcdef__

public class Replace { 

    public static void replaceChar(String str,String target){ 
     String result = str.replaceAll(target, "_"); 
     System.out.println(result); 
    } 

    public static void main(String[] args) { 
     replaceChar("abcdefaa","a"); 
    } 

} 
Powiązane problemy