2015-06-26 14 views
5

Próbuję sformatować ciąg w java, używając klasy MessageFormat. Ciąg zawiera pole pozycyjne, ale działa tylko wtedy, gdy podam numer pola. Na przykładAutomatyczne numerowanie pól w formatowaniu ciągów znaków

MessageFormat.format("{0} {1}", "Hi", "Java") prace ale

MessageFormat.format("{} {}", "Hi", "Java") daje

Exception in thread "main" java.lang.IllegalArgumentException: can't parse argument number: 
    at java.text.MessageFormat.makeFormat(MessageFormat.java:1429) 
    at java.text.MessageFormat.applyPattern(MessageFormat.java:479) 
    at java.text.MessageFormat.<init>(MessageFormat.java:362) 
    at java.text.MessageFormat.format(MessageFormat.java:840) 
    at controller.App.main(App.java:11) 
Caused by: java.lang.NumberFormatException: For input string: "" 
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) 
    at java.lang.Integer.parseInt(Integer.java:592) 
    at java.lang.Integer.parseInt(Integer.java:615) 
    at java.text.MessageFormat.makeFormat(MessageFormat.java:1427) 

czy istnieje sposób (innej klasy lub biblioteki), że może obsługiwać zarówno automatyczne i ręczne polu numerowania coś jak python robi?

In [3]: print "{} {}".format("Hi", "Java") 
Hi Java 

In [4]: print "{0} {1}".format("Hi", "Java") 
Hi Java 
+0

Jeśli nie chcesz, aby zapewnić indeksy, a następnie użyć 'String.format' zamiast. – Tom

+0

Tak, mogę to zrobić, ale mam przypadek użycia, gdzie mogę uzyskać ciąg z lub bez indeksów – barunsthakur

Odpowiedz

1

dodanie do @JohnH odpowiedź string.Format mógł robić automatyczne i ręczne indeksy pól do formatowania String.

String.format("%s %s", "Hi", "Java") 
String.format("%1$s %2$s %1$s", "Hi", "Java") 

Reference Doc

To nie jest ergonomiczna niż "{1} {2}" ale dostaje zadanie.

2

Brzmi jak String.format(), którego szukasz.

String foo = String.format("%s %s", "Hi", "Java") 
StringBuffer bar = new StringBuffer(foo); 
3

można zrobić następujące Hack:

String.format("{} {}".replace("{}", "%s"), new String[]{"Hi", "Java"})); 

To pierwszy zastępuje {} z %s, a następnie zastąpić każdą %s z odpowiednią wartość z tablicy Ciebie ciąg jako argument dla format metody.

Należy pamiętać, że od format akceptuje Object... args jako drugi argument, można napisać:

String.format("{} {}".replace("{}", "%s"), "Hi", "Java"); 
+0

Tak, to będzie działać, ale nie to, co chcę. Również to nie pomoże w pozycjonowaniu indeksów argumentów. – barunsthakur

+0

@barunsthakur Musisz sprawdzić, której wersji potrzebujesz. Spróbuj użyć wyrażenia regularnego. – Tom

0

używam slf4j do logowania, który umożliwia zalogowanie ciąg tak:

LoggerFactory.getLogger("name").debug("{} {}", "Hello", "World"); 

Wystarczy zajrzał do kodu źródłowego, aby zobaczyć, co to było używane do sformatowania ciągu, i używa tej klasy:

org.slf4j.helpers.MessageFormatter 

Dostępne są 3 metody. 1 przez zastąpienie jednego obiektu:

MessageFormatter.format(String message, Object arg); 

Jeden zastąpić 2 obiekty:

MessageFormatter.format(String message, Object arg1, Object arg2); 

i jeden zastąpić szereg obiektów:

MessageFormatter.arrayFormat(String message, Object[] argArray); 

Te wszystkie zwrócić obiekt typu FormattingTuple. Aby uzyskać sformatowany ciąg z obiektu, należy zadzwonić FormattingTuple.getMessage();

Aby skorzystać z tej obok ręcznej numeracji pola, spojrzeć na poniższy sposób:

public String formatString(String original, Object... replacements) { 
    String stringToReturn = original; 
    for (int i = 0; i < replacements.length; i++) { 
     stringToReturn = stringToReturn.replaceAll("\\{" + i + "\\}", replacements[i].toString()); 
    } 
    return MessageFormatter.arrayFormat(stringToReturn, replacements).getMessage(); 
} 
+1

'System.out.println (MessageFormatter.format (" {1} {2} {1} "," hi "," java "). GetMessage());' output '{1} {2} {1} '. – barunsthakur

+0

Twoje pytanie wskazuje, że chciałeś to zrobić bez określania pola pozycyjnego. 'System.out.println (MessageFormatter.format (" {} {} "," hi "," java "). GetMessage());' output 'hi java' –

+0

Nie." Że może obsłużyć automatyczne i ręczna numeracja pól " – barunsthakur

1

Użyłbym wzoru opublikowanego przez Marouna Marouna, gdybym był ograniczony do standardowych bibliotek, takich jak barunsthakur.

Sprytny pomysł Ben Greens przydaje się każdemu, kto korzysta z sfl4j podczas logowania z nieindeksowanymi argumentami, oprócz przygotowywania łańcuchów ręcznie z indeksowanymi argumentami.

Była jedna wada dla mnie: mogę używać zarówno indeksowane i indeksowane argumenty nie teraz, ale nie jestem w stanie użyć opcji FormatType i FormatStyle z java.text.MessageFormat.format(), na przykład {0, numer, waluta}.

Tak więc stworzyłem rozszerzoną wersję rozwiązania Bena, które wykorzystuje wszystkie 3 warianty.

import org.slf4j.helpers.MessageFormatter; 
import java.text.MessageFormat; 
import java.util.regex.Matcher; 
import java.util.regex.Pattern; 

public static String format(String original, Object... replacements) 
{ 
    if (Pattern.matches(".*\\{\\d+,.+,.+\\}.*", original)) 
    { 
     return MessageFormat.format(original, replacements); 
    } 
    else 
    { 
     String r = "\\{\\d\\}"; 

     if(original.matches(".*" + r + ".*")) 
     { 
      Pattern p = Pattern.compile(r); 
      Matcher m = p.matcher(original); 
      StringBuffer b = null; 
      int i = 0; 

      while(m.find()) 
      { 
       if(b == null) b = new StringBuffer(); 
       m.appendReplacement(b, replacements[i].toString()); 
       i++; 
      } 
      m.appendTail(b); 
      return (i > 0) ? b.toString() : null; 
     } 
     else 
     { 
      return MessageFormatter.arrayFormat(original, replacements).getMessage(); 
     } 
    } 
} 

unit-Testy:

String expected = "pink is a disgusting color"; 
String actual = StringHelpers.format("{0} is a disgusting {1}", "pink", "color"); 
assertEquals(expected, actual); 

expected = "01-02-2017 was a rather meh day"; 
actual = StringHelpers.format("{0,date,MM-dd-YYYY} was a rather {1} day", new Date(117,0,2), "meh"); 
assertEquals(expected, actual); 

expected = "One Person expects the danish inquisition"; 
actual = StringHelpers.format("{} expects the {} inquisition", "One Person", "danish"); 
assertEquals(expected, actual); 
Powiązane problemy