2010-06-27 34 views
36

Làm cách nào để định dạng chuỗi của tôi trong GWT?Trình định dạng chuỗi trong GWT

tôi đã thực hiện một phương pháp

Formatter format = new Formatter(); 
    int matches = 0; 
    Formatter formattedString = format.format("%d numbers(s, args) in correct position", matches); 
    return formattedString.toString(); 

Nhưng nó than phiền bằng cách nói

Validating newly compiled units 
    [ERROR] Errors in 'file:/C:/Documents%20and%20Settings/kkshetri/workspace/MasterMind/MasterMind/src/com/kunjan/MasterMind/client/MasterMind.java' 
     [ERROR] Line 84: No source code is available for type java.util.Formatter; did you forget to inherit a required module? 

Không phải là định dạng bao gồm?

+0

u đã nhập java.util.Formatter trong tập tin MasterMind.java của bạn? –

Trả lời

21

CẬP NHẬT: Vui lòng xem (và bỏ phiếu) bài đăng của Joseph Lust bên dưới trước khi xem thêm câu trả lời này.

Có vẻ như trình định dạng không được bao gồm theo this post. Tuy nhiên, họ đề xuất một số lựa chọn thay thế.

+5

Giá trị đề cập cũng là 'NumberFormat' và' DateTimeFormat'. –

+0

IDE của tôi phàn nàn rằng NumberFormat không có trong mô phỏng JRE nhưng có vẻ như hoạt động ... – dhardy

+0

Đây là giải pháp [GWT Solution] thực sự, hợp pháp [http://www.gwtproject.org/doc/latest/DevGuideCodingBasicsFormatting.html# numberformat) cho tôi. [như được tham chiếu bởi câu trả lời @Joseph Lust bên dưới mà tôi nghĩ rằng đó là câu trả lời được chấp nhận thực sự ..] – cellepo

21

Một thay thế rất đơn giản cho String.format() trong 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

Là một thay thế, bạn có thể sử dụng lớp NumberFormat:

NumberFormat fmt = NumberFormat.getDecimalFormat(); 
double value = 12345.6789; 
String formatted = fmt.format(value); 
// Prints 1,2345.6789 in the default locale 
0

khác thay thế rất rất đơn giản cho java. text.MessageFormat.format():

public static String format(final String format, final Object... args) { 
    StringBuilder sb = new StringBuilder(); 
    int cur = 0; 
    int len = format.length(); 
    while (cur < len) { 
     int fi = format.indexOf('{', cur); 
     if (fi != -1) { 
      sb.append(format.substring(cur, fi)); 
      int si = format.indexOf('}', fi); 
      if (si != -1) { 
       String nStr = format.substring(fi + 1, si); 
       int i = Integer.parseInt(nStr); 
       sb.append(args[i]); 
       cur = si + 1; 
      } else { 
       sb.append(format.substring(fi)); 
       break; 
      } 
     } else { 
      sb.append(format.substring(cur, len)); 
      break; 
     } 
    } 
    return sb.toString(); 
} 
5

Hoặc thậm chí đơn giản hơn, không sử dụng RegE xp, và chỉ sử dụng 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(); 
} 
+3

'pos + = 1' trong vòng lặp' for'? Có thật không? –

+1

+1 vì không sử dụng gói google. Điều này có vấn đề nếu định dạng kết thúc bằng '% s'. Chỉ cần thêm 'if (args.length == split.chiều dài) \t \t msg.append (args [args.length - 1]); 'trước khi trở về sửa lỗi. –

+0

trừ phân tách chuỗi không có sẵn trong gwt – NimChimpsky

1

Cái này là khá nhanh và bỏ qua các giá trị xoăn được phân định xấu:

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

Xem official page vào ngày GWT và định dạng số.

Họ đề nghị như sau:

myNum decimal = 33.23232; 
myString = NumberFormat.getFormat("#.00").format(decimal); 

Nó là tốt nhất để sử dụng, phương pháp tối ưu hóa hỗ trợ của họ, hơn là nấu lên phương pháp không tối ưu của riêng bạn. Trình biên dịch của họ sẽ được tối ưu hóa tất cả để gần như cùng một điều anyway cuối cùng.

0

Có lẽ cách dễ nhất để làm điều gì đó như String.format, có thể làm điều đó bằng một Chuỗi.thay thế, ví dụ;

thay vì làm String.format("Hello %s", "Daniel"); ==>"Hello %s".replace("%s", "Daniel"),

cả cho chúng ta những kết quả tương tự, nhưng chỉ cách thứ hai làm việc tại phía khách hàng GWT

+1

Nếu bạn định sử dụng định dạng, bạn có thể cần nhiều tham số, do đó, thay thế mù của "% s" không thực sự là giải pháp. –

1

Tôi không quan tâm đến việc lạm dụng chuỗi thao tác để thực hiện regexps 'công việc, nhưng, dựa trên giải pháp bodrin, bạn có thể mã hóa:

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; 
} 
+1

Điều gì đó làm tôi sợ về việc sửa đổi thông số của bạn trong phương thức của bạn. –

+0

@RyanShillington Chuỗi là không thay đổi. – NateS

3

một gợi ý mà làm cho sử dụng JSNI và một chức năng định dạng hoạt Javascript đẹp từ another post:

import com.google.gwt.core.client.JsArrayString; 

public abstract class StringFormatter { 
    public static String format(final String format, final Object... args) { 
     if (null == args || 0 == args.length) 
      return format; 
     JsArrayString array = newArray(); 
     for (Object arg : args) { 
      array.push(String.valueOf(arg)); // TODO: smarter conversion? 
     } 
     return nativeFormat(format, array); 
    } 

    private static native JsArrayString newArray()/*-{ 
     return []; 
    }-*/; 

    private static native String nativeFormat(final String format, final JsArrayString args)/*-{ 
     return format.replace(/{(\d+)}/g, function(match, number) { 
      return typeof args[number] != 'undefined' ? args[number] : match; 
     }); 
    }-*/; 
} 

Một sau đó có thể thực hiện cuộc gọi như thế này:

StringFormatter.format("Greetings {0}, it's {1} o'clock, which is a {2} statement", "Master", 8, false); 

... với kết quả là

Chúc mừng Thầy, đó là 8:00, đó là một tuyên bố sai sự thật

Có khả năng cải thiện thêm tại TODO nhận xét, ví dụ: sử dụng NumberFormat. Đề xuất được hoan nghênh.

0

Như đã đề cập ở trên, có các trình định dạng GWT cho các số và ngày: NumberFormatDateTimeFormat. Tuy nhiên, tôi cần một giải pháp cho trường hợp nổi tiếng String.format(...). Tôi kết thúc với giải pháp này, tôi không biết nếu nó sai cho hiệu suất, nhưng nó là trực quan sạch sẽ. Tôi rất vui khi nghe bất kỳ bình luận nào về nó, hoặc về giải pháp khác.

My Chuỗi định dạng:

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

} 

và JUTest nếu muốn tái sử dụng này:

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

} 
1

Một phần mở rộng để giải pháp Daniels: Cũng hỗ trợ thoát sử dụng 'và ném nếu một số không thể phân tích cú pháp (như phiên bản JVM):

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

Triển khai này và JVM-Versi trên cả hai vượt qua những bài kiểm tra:

// 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"); 

Thoát-Các xét nghiệm:

// 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 
    }