1

I need to find special escape java chars (\n, \t, \b, etc.) in a grooup of strings and then print what strings contain which special chars. So, when printing I would like to change the char value itself by a string "\n" for '\n', "\t" for '\t' and so on. I did with a switch statement for all this type of characters. I wonder if there is a solution that doesn't involve checking for each one of the???

Carlos Blanco
  • 8,592
  • 17
  • 71
  • 101

7 Answers7

1

Hmm, I don't think regular expressions will let you do this replacement in one line, even with back references. The problem is injecting the knowledge that the newline character maps to "\n" and so on for all special characters.

You can of course do it with a series of replace() calls, one for each character, but you're trying to avoid that.

You need the equivalent of the 'tr' command in Unix, and I'm sorry to say I don't know of such a method.

Sean Owen
  • 66,182
  • 23
  • 141
  • 173
1

I didn't find a library for that, but on the other hand, my quick implementation doesn't look too terrible - I'd prefer this even over a RegExp ;)

public String unescape(String s) {
    StringBuilder result = new StringBuilder();
    for (char c : s.toCharArray()) {
        result.append(toLiteral(c));
    }
    return result.toString();
}

private String toLiteral(char c) {
    switch (c) {
    case '\n':
        return "\\n";
    case '\t':
        return "\\t";
    case '\r':
        return "\\r";
    case '\f':
        return "\\f";
    case '\b':
        return "\\b";
    case '\'':
        return "\\\'";
    case '\"':
        return "\\\"";
    case '\\':
        return "\\\\";
    default:
        return c;
    }
}

According to my compiler, theses are all escape sequences that are allowed for Strings.

Andreas Dolk
  • 113,398
  • 19
  • 180
  • 268
  • I don't think you need to have the '\'' characters. I think that the questioner was asking to replace '\n' with "\\n". – Paul Wagland Jan 22 '10 at 21:54
  • Yeah, this was the implementation I also came up with. I think that's what I'm gonna use. – Carlos Blanco Jan 22 '10 at 22:09
  • As an aside, the `"\\\'"` string can be simplified to `"\\'"`, and `'\"'` to `'"', since ' does not need to be escaped in a string, and " doesn't need to be escaped in a character. – Paul Wagland Jan 22 '10 at 22:16
1

At the end of the day, no matter what method is used, something will need to look at every character in the string. You can either do explicitly in a loop, like you are now, or by chaining a set of replace() calls. But, while these might look shorter on paper, they are likely to take longer.

To do this using replace():

"\ttest\n\n".replace("\t", "\\t").replace("\n", "\\n")/*…*/;

To do this in a loop, look at the answer from Andreas_D.

Do note that the replace() method, while shorter on paper, will almost certainly take longer to run, since it has to loop over the entire string 8 times, once to replace each escape sequence, whereas the manual loop only needs to do it once.

Edit: Initially I thought that you could probably do it with a magic regex, however you can't do conditional replacement in the regex, meaning that you could only do the equivalent of the replace calls shown above. Given that regexes will be slightly slower in this case, I don't think that this is a good solution.

Community
  • 1
  • 1
Paul Wagland
  • 27,756
  • 10
  • 52
  • 74
1

A different approach using a map to decide replacement and StringBuilder.replace method to actually perform the replacement, it looks a bit more compact and I guess it is not far from the switch version in performance but certainly using a bit more of memory.

public class Unescape {

    private static final Map<Character, String> replacements = new HashMap<Character, String>(){{
        put('\n',"\\n"); put('\r',"\\r"); put('\t',"\\t"); put('\b',"\\b"); //etc
    }};

    public static String unescape(String s) {
        String replace;
        StringBuilder result = new StringBuilder(s);
        for (int i=0; i < result.length(); i++) {
            replace = replacements.get(result.charAt(i));
            if (replace!=null) result.replace(i, i+1, replace);
        }
        return result.toString();
    }

    public static void main(String[] args) {

        System.out.println(unescape("hi\nthere\t\t\tHow are u?"));

    }

}

the output of the sample is

hi\nthere\t\t\tHow are u?

Miquel
  • 4,741
  • 3
  • 20
  • 19
  • StringBuilders replace method always calls System.arraycopy. This may kill performance if used on large inputs (text files). On the other hand I like that the solution is based on a map (BTW: should be named REPLACEMENTS because constants are usually in upper case) – Andreas Dolk Jan 22 '10 at 23:48
0

You might use regular expressions:

String.replaceAll

Randolpho
  • 55,384
  • 17
  • 145
  • 179
0

If you’re looking for something a tad fancier, you might look at this answer.

Community
  • 1
  • 1
tchrist
  • 78,834
  • 30
  • 123
  • 180
0

org.apache.commons.lang.StringEscapeUtils.(un)EscapeJava methods are probaby what you want to do this both ways...

Answer from brainzzy not mine :

https://stackoverflow.com/a/8736043/1130448

Community
  • 1
  • 1
sinekonata
  • 364
  • 3
  • 11