如何在Java中替换字符串中的字符?


70

使用Java,我想遍历文本的各个行,并用&XML实体引用替换所有的&符号()&

我先扫描文本行,然后再使用Scanner类扫描文本中的每个单词。然后,我使用CharacterIterator遍历单词的每个字符。但是,如何替换字符?首先,字符串是不可变的对象。其次,我想&用几个character(amp&;)替换一个character()。我应该如何处理?

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

       }
}

Answers:


126

尝试使用String.replace()String.replaceAll()代替。

String my_new_str = my_str.replace("&", "&");

(都替换所有出现的内容;replaceAll允许使用正则表达式。)


71
请注意replaceAll,因为它将第一个参数用作正则表达式。即“ hello” .replaceAll(“。”,“,”)将为您提供“ 、、、、、、、、”!在Java 1.5中,有一个新的String.replace(CharSequence,CharSequence)方法,该方法执行类似的操作,但不会将第一个参数解释为正则表达式。
PeterŠtibraný09年

1
@PeterŠtibraný或...您可以逃脱要替换的字符:replaceAll("[.]", ",")
Yassin Hajaj

1
这不是逃脱角色的方式。我认为peter的要点是,当您不需要正则表达式时就可以避免意外的副作用。
user4504267 '18

91

简单的答案是:

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

尽管名称与replaceAll相比,replace确实执行了replaceAll,但它只是不使用正则表达式,这似乎在这里是有顺序的(从性能和良好实践的角度来看-不要偶然使用正则表达式因为它们有特殊的字符要求,您不会关注)。

如果您已经知道此代码是性能的热点,而这正是您提出问题的地方,那么在缺少性能和性能测试的其他目标要求的情况下,从性能角度考虑,Sean Bright的回答可能就足够了。当然,这不值得被否决。除非需要同步,否则仅使用StringBuilder而不是StringBuffer。

话虽这么说,这里还有一个更深层次的潜在问题。转义字符是一个已知问题,许多库都在其中解决。您可能需要考虑将数据包装在XML的CDATA部分中,或者您可能更喜欢使用XML库(包括现在JDK附带的库)来实际生成XML(以便它可以处理编码) )。

作为Commons Lang的一部分,Apache还具有一个转义库


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
在这种情况下,您不需要StringBuffer。
泰勒里斯

2
相反,使用String会导致每次迭代创建一个临时的String对象。我不确定您会建议哪种选择。
肖恩·布莱特2009年

4
+1:不确定为什么会收到2个否决票-可能比replaceAll()更有效-毕竟为什么只在单个字符上进行匹配就使用正则表达式?
亚当斯基

6
在我之前的评论中,我只是针对5000个字符串(其中大约10%的字符为“&”)测量了replaceAll和Sean解决方案的性能-平均replaceAll时间为0.92ms,而Sean解决方案为0.29ms。使用StringBuilder可以将时间进一步缩短至0.23ms。
亚当斯基

3
这不是过早的优化-这是我对问题的回答。它的发生速度也比快String.replaceAll(),但这不是建议这样做的原因。
肖恩·布莱特2009年

9

您可能还需要检查以确保不替换已替换的事件。您可以使用具有负前瞻性的正则表达式来执行此操作。

例如:

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

这将导致字符串“ sdasdasa&amp;adas&amp;dasdasa”。

正则表达式模式“&(?! amp;)”基本上说:匹配任何出现的“&”,而不是“ amp;”。


5

只需创建一个包含所有相关数据的字符串,然后使用String.replaceAll()即可,如下所示。

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

如果数据太大,则创建包含所有数据的单个字符串可能是不利的。我们也可以逐行进行。
虎山

在这种情况下使用replaceAll是错误的!如果可能,请始终使用replace代替replaceAll。它更高效,更不容易出错。
John Henckel 2014年


1

尝试使用此代码。您可以将任何字符替换为另一个给定字符。在这里,我试图替换字母“A”“ - ”字符的字符串给予“abcdeaa”

输出-> _ 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");
    }

}

1

您可以使用streamflatMap映射&&amp;

    String str = "begin&end";
    String newString = str.chars()
        .flatMap(ch -> (ch == '&') ? "&amp;".chars() : IntStream.of(ch))
        .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)
        .toString();

0

如果您使用的是Spring,则只需调用即可HtmlUtils.htmlEscape(String input)处理“&”到“&”转换。


这是有风险的,因为与纯XML相比,HTML定义的实体更多。
克里斯·韦斯特

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);
            }
        }
    }

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.