String Formatter in GWT

前端 未结 12 649
生来不讨喜
生来不讨喜 2021-02-03 18:59

How do I format my string in GWT?

I made a method

  Formatter format = new Formatter();
    int matches = 0;
    Formatter formattedString = format.forma         


        
相关标签:
12条回答
  • 2021-02-03 19:37

    This one is pretty fast and ignores bad curly-delimited values:

    public static String format(final String format, final Object... args)
    {
        if (format == null || format.isEmpty()) return "";
    
        // Approximate the result length: format string + 16 character args
        StringBuilder sb = new StringBuilder(format.length() + (args.length*16));
    
        final char openDelim = '{';
        final char closeDelim = '}';
    
        int cur = 0;
        int len = format.length();
        int open;
        int close;
    
        while (cur < len)
        {
            switch (open = format.indexOf(openDelim, cur))
            {
                case -1:
                    return sb.append(format.substring(cur, len)).toString();
    
                default:
                    sb.append(format.substring(cur, open));
                    switch (close = format.indexOf(closeDelim, open))
                    {
                        case -1:
                            return sb.append(format.substring(open)).toString();
    
                        default:
                            String nStr = format.substring(open + 1, close);
                            try
                            {
                                // Append the corresponding argument value
                                sb.append(args[Integer.parseInt(nStr)]);
                            }
                            catch (Exception e)
                            {
                                // Append the curlies and the original delimited value
                                sb.append(openDelim).append(nStr).append(closeDelim);
                            }
                            cur = close + 1;
                    }
            }
        }
    
        return sb.toString();
    }
    
    0 讨论(0)
  • 2021-02-03 19:40

    Or even simpler, not using RegExp, and using only Strings:

    public static String format(final String format, final String... args) {
        String[] split = format.split("%s");
        final StringBuffer msg = new StringBuffer();
        for (int pos = 0; pos < split.length - 1; pos += 1) {
            msg.append(split[pos]);
            msg.append(args[pos]);
        }
        msg.append(split[split.length - 1]);
        return msg.toString();
     }
    
    0 讨论(0)
  • 2021-02-03 19:52

    As mentionned above, there is GWT formatters for numbers and dates : NumberFormat and DateTimeFormat. Still, I needed a solution for the well-know String.format(...) case. I end up with this solution, I don't know if it's wrong for performance, but it's visually clean. I'd be glad to hear any comment on it, or about other solution.

    My String formatter :

    public class Strings {
    
        public static String format(final String format, final Object... args) {
            String retVal = format;
            for (final Object current : args) {
                retVal = retVal.replaceFirst("[%][s]", current.toString());
            }
            return retVal;
        }
    
    }
    

    and the JUTest if one want to re-use this :

    public class StringsTest {
    
        @Test
        public final void testFormat() {
            this.assertFormat("Some test here  %s.", 54);
            this.assertFormat("Some test here %s and there %s, and test [%s].  sfsfs !!!", 54, 59, "HAHA");
    
        }
    
        private void assertFormat(final String format, final Object... args) {
            Assert.assertEquals("Formatting is not working", String.format(format, args), Strings.format(format, args));
        }
    
    }
    
    0 讨论(0)
  • 2021-02-03 19:53

    I'm not keen on abusing string manipulation for doing regexps' job, but, based on bodrin's solution, you can code:

    public static String format (String pattern, final Object ... args) {
        for (Object arg : args) {
            String part1 = pattern.substring(0,pattern.indexOf('{'));
            String part2 = pattern.substring(pattern.indexOf('}') + 1);
            pattern = part1 + arg + part2;
        }   
        return pattern;
    }
    
    0 讨论(0)
  • 2021-02-03 19:54

    A very simple replacement for String.format() in GWT 2.1+:

    import com.google.gwt.regexp.shared.RegExp;
    import com.google.gwt.regexp.shared.SplitResult;
    
    public static String format(final String format, final Object... args) {
      final RegExp regex = RegExp.compile("%[a-z]");
      final SplitResult split = regex.split(format);
      final StringBuffer msg = new StringBuffer();
      for (int pos = 0; pos < split.length() - 1; ++pos) {
        msg.append(split.get(pos));
        msg.append(args[pos].toString());
      }
      msg.append(split.get(split.length() - 1));
      return msg.toString();
    }
    
    0 讨论(0)
  • 2021-02-03 19:54

    An extension to Daniels solution: Also supports escaping using ' and throws if a number cannot be parsed (like the JVM version does):

    private static final char OPEN = '{';
    private static final char CLOSE = '}';
    private static final char ESCAPE = '\'';
    
    @Override
    public String format(String pattern, Object... arguments) {
        if (pattern == null || pattern.isEmpty())
            return "";
    
        // Approximate the result length: format string + 16 character args
        StringBuilder sb = new StringBuilder(pattern.length() + (arguments.length * 16));
    
        int cur = 0;
        int len = pattern.length();
        // if escaped, then its >= 0
        int escapedAtIndex = -1;
    
        while (cur < len) {
            char currentChar = pattern.charAt(cur);
            switch (currentChar) {
                case OPEN:
                    if (escapedAtIndex >= 0) {
                        // currently escaped
                        sb.append(currentChar);
                    } else {
                        // find close
                        int close = pattern.indexOf(CLOSE, cur + 1);
                        switch (close) {
                            case -1:
                                // Missing close. Actually an error. But just ignore
                                sb.append(currentChar);
                                break;
                            default:
                                // Ok, we have a close
                                final String nStr = pattern.substring(cur + 1, close);
                                try {
                                    // Append the corresponding argument value
                                    sb.append(arguments[Integer.parseInt(nStr)]);
                                } catch (Exception e) {
                                    if (e instanceof NumberFormatException) {
                                        throw new IllegalArgumentException(nStr +
                                                " is not a number.");
                                    }
                                    // Append the curlies and the original delimited value
                                    sb.append(OPEN).append(nStr).append(CLOSE);
                                }
                                // Continue after the close
                                cur = close;
                                break;
                        }
                    }
                    cur++;
                    break;
                case ESCAPE:
                    // Special case: two '' are just converted to '
                    boolean nextIsEscapeToo = (cur + 1 < len) && pattern.charAt(cur + 1) == ESCAPE;
                    if (nextIsEscapeToo) {
                        sb.append(ESCAPE);
                        cur = cur + 2;
                    } else {
                        if (escapedAtIndex >= 0) {
                            // Escape end.
                            escapedAtIndex = -1;
                        } else {
                            // Escape start.
                            escapedAtIndex = cur;
                        }
                        cur++;
                    }
                    break;
                default:
                    // 90% case: Nothing special, just a normal character
                    sb.append(currentChar);
                    cur++;
                    break;
            }
        }
        return sb.toString();
    }
    

    This implementation and the JVM-Version both pass those tests:

        // Replace: 0 items
        assertFormat("Nothing to replace", "Nothing to replace");
        // Replace: 1 item
        assertFormat("{0} apples", "15 apples", 15);
        assertFormat("number of apples: {0}", "number of apples: zero", "zero");
        assertFormat("you ate {0} apples", "you ate some apples", "some");
        // Replace 2 items
        assertFormat("{1} text {0}", "second text first", "first", "second");
        assertFormat("X {1} text {0}", "X second text first", "first", "second");
        assertFormat("{0} text {1} X", "first text second X", "first", "second");
    

    Escaping-Tests:

        // Escaping with no replacement
        assertFormat("It's the world", "Its the world");
        assertFormat("It''s the world", "It's the world");
        assertFormat("Open ' and now a second ' (closes)", "Open  and now a second  (closes)");
        assertFormat("It'''s the world", "It's the world");
        assertFormat("'{0}' {1} {2}", "{0} one two", "zero", "one", "two");
        // Stays escaped (if end escape is missing)
        assertFormat("'{0} {1} {2}", "{0} {1} {2}", "zero", "one", "two");
        assertFormat("'{0} {1}' {2}", "{0} {1} two", "zero", "one", "two");
        // No matter where we escape, stays escaped
        assertFormat("It's a {0} world", "Its a {0} world", "blue");
        // But we can end escape everywhere
        assertFormat("It's a {0} world, but not '{1}",
                "Its a {0} world, but not always", "blue", "always");
        // I think we want this
        assertFormat("It''s a {0} world, but not {1}",
                "It's a blue world, but not always", "blue", "always");
        // Triple
        assertFormat("' '' '", " ' ");
        // From oracle docs
        assertFormat("'{''}'", "{'}");
        // Missing argument (just stays 0)
        assertFormat("begin {0} end", "begin {0} end");
        // Throws
        try {
            assertFormat("begin {not_a_number} end", "begin {not_a_number} end");
            throw new AssertionError("Should not get here");
        } catch (IllegalArgumentException iae) {
            // OK
        }
    
    0 讨论(0)
提交回复
热议问题