0

I've needed a replace() method which could replace a needle String within a haystack String, in a case insensitive way. I also needed this to be done without any regex. I couldn't find any such method, so I've written my own. This question is to document it, in case anyone else finds it useful in future. And if any improvements can be made (without using String.replace), feel free to suggest them.

Ali
  • 261,656
  • 265
  • 575
  • 769
  • possible duplicate of [How to replace case-insensitive literal substrings in Java](http://stackoverflow.com/questions/5054995/how-to-replace-case-insensitive-literal-substrings-in-java) – Braj Jun 06 '14 at 20:50
  • Why you don't want to use `replace()` and `repalceAll()` method? Is there any specific reason behind it? – Braj Jun 06 '14 at 20:51
  • @Braj I need the replace to be case insensitive, and also, I'm using google web tookit, which compiles the java code to javascript. So the regexes, etc have to be javascript compatible. And so there isn't an easy way available to escape user input so it can be used in replaceAll. – Ali Jun 06 '14 at 20:55
  • Why do you worry about the Java code to JavaScript? Just leave it for GWT compiler. If GWT supports that API or methods then you can use it at client side. – Braj Jun 06 '14 at 20:58
  • @Braj GWT doesn't support java style regular expressions. – Ali Jun 06 '14 at 21:13
  • Read it here [com.google.gwt.regexp.shared.RegExp](http://www.gwtproject.org/javadoc/latest/com/google/gwt/regexp/shared/RegExp.html) that is designed for regular expressions with features like `Javascript's RegExp`, plus Javascript String's `replace` and split methods (which can take a RegExp parameter). – Braj Jun 06 '14 at 21:15
  • @Braj I already have, `Java-specific constructs in the regular expression syntax (e.g. [a-z&&[^bc]], (?<=foo), \A, \Q) work only in the pure Java implementation, not the GWT implementation` – Ali Jun 06 '14 at 21:16
  • Try [RegExp#replace()](http://www.gwtproject.org/javadoc/latest/com/google/gwt/regexp/shared/RegExp.html#replace%28java.lang.String,%20java.lang.String%29). – Braj Jun 06 '14 at 21:18
  • @Braj I need it to be case insensitive, and work on user input strings (which can contain special chars like `.^$` etc, which would be interpreted as regexes) – Ali Jun 06 '14 at 21:20
  • If you can do it in `JavaScript` then simply use it. In GWT you can call it using `JSNI` and I hope you know it. Have a look at [Case insensitive string replacement in JavaScript?](http://stackoverflow.com/questions/280793/case-insensitive-string-replacement-in-javascript). Read what `GWT RegExp` says as I mentioned in my above comments. – Braj Jun 06 '14 at 21:24
  • @Braj It would be done in the same method in javascript (i.e with indexOf) that I'm using now, since there's no easy way to escape user input in js – Ali Jun 06 '14 at 21:27
  • Have you visited any link that I shared you? Sorry I can't help you anymore. If you have written it already it then why are you asking this question here. Simply post it for [code review](http://codereview.stackexchange.com/). – Braj Jun 06 '14 at 21:27
  • @Braj `This question is to document it, in case anyone else finds it useful in future` – Ali Jun 06 '14 at 21:29

2 Answers2

1
public static String replace(String needle, String hayStack, String replacement)
{
    String origNeedle = needle;
    String origHayStack = hayStack;

    needle = origNeedle.toLowerCase();
    hayStack = origHayStack.toLowerCase();

    int hayStackLen = hayStack.length();
    int needleLen = needle.length();
    int from = 0;
    int to;

    String stuffBeforeNeedle;
    StringBuilder output = new StringBuilder();

    do
    {
        to = hayStack.indexOf(needle, from);
        if (to == -1)
            to = hayStackLen;

        stuffBeforeNeedle = hayStack.substring(from, to);
        output.append(stuffBeforeNeedle);

        if (to < hayStackLen)
            output.append( replacement );

        from = hayStack.indexOf(needle, to) + needleLen;
    }
    while (to < hayStackLen);

    return output.toString();
}
Ali
  • 261,656
  • 265
  • 575
  • 769
0
public static void main(String[] args) throws IOException, ApplicationException, InterruptedException
{
    String output = "";

    String haystack = "This is the end. The beautiful EnD.  No safety or surprise, the eND. La la la!";
    String needle = "eNd";

    String replacement = "beginning";

    String searchHaystack = haystack.toLowerCase();
    String searchNeedle = needle.toLowerCase();

    int substringStart = 0;
    int beginningOfNeedle = -1;
    while(true)
    {           
        // Finds the first needle in the haystack, starting the search just after the last one we found.
        // (On the first iteration, we start from the first character).
        beginningOfNeedle = searchHaystack.indexOf(searchNeedle, ++beginningOfNeedle);

        // If we can't find another needle, we're done.
        if(beginningOfNeedle == -1)
            break;          

        // If we found a needle, we add to our output the substring of haystack
        // that starts from substringStart and goes right up to the beginning of the needle
        // we just found.
        output += haystack.substring(substringStart, beginningOfNeedle);
        // We also add the replacement text.
        output += replacement;

        // The next substring will start right at the end of the needle.
        substringStart = beginningOfNeedle + needle.length();
    }
    // We add the last substring (which runs through the end of the haystack)
    // to the output.
    output += haystack.substring(substringStart);


    System.out.println(output);
}