2016-05-24 22 views
1

In einem Java-Programm verwende ich eine Zeichenfolge mit Formatter.format() Funktion, die ich vom Server bekomme. Ich kann nicht sicher sein, dass String formatiert Platzhalter oder eine gültige Anzahl von ihnen hat. Wenn es die String nicht wie erwartet ist, möchte ich eine Ausnahme auslösen - oder es irgendwie protokollieren.Anzahl der Platzhalter in Formatter.format() String

An diesem Punkt ist mir egal, welche Art von Platzhaltern sind (String, Integer, ...), ich möchte nur die Anzahl der erwarteten Parameter für jeden String erhalten.

Was ist der einfachste Weg, dies zu erreichen? Eine Möglichkeit wäre, eine Regex zu verwenden, aber ich denke, wenn es etwas Bequemeres gibt - zum Beispiel eine eingebaute Funktion.

Hier sind einige Beispiele:

Example String | number of placeholders: 
%d of %d   | 2 
This is my %s  | 1 
A simple content. | 0 
This is 100%  | 0 
Hi! My name is %s and I have %d dogs and a %d cats. | 3 

EDIT: Formatter.format() löst eine Ausnahme aus, wenn nicht genügend zur Verfügung gestellt Parameter sind. Es besteht die Möglichkeit, dass ich einen String ohne Platzhalter bekomme. In diesem Fall, selbst wenn ich Parameter zur Verfügung stelle (wird weggelassen), wird keine Ausnahme geworfen (obwohl ich eine werfen möchte), nur dass der String-Wert zurückgegeben wird. Ich muss den Fehler dem Server melden.

+0

Auf welche Weise kann es sein, "nicht das, was Sie erwarten"? Vermutlich kennen Sie die Anzahl der Platzhalter, die Sie erwarten - können Sie einfach versuchen, mit Standardwerten zu formatieren und zu sehen, ob es fehlschlägt? –

+0

Ich weiß nicht über eine eingebaute Funktion, aber mein erster Gedanke ist Regex ist der Weg zu gehen. Haben Sie spezielle Bedenken bezüglich der Verwendung von Regex? – Hill

+0

@AndyTurner Ich war nicht klar genug. Ich weiß, dass Format-Methode eine Ausnahme auslöst, wenn ich nicht genug Parameter zur Verfügung stelle. Mein Problem ist, dass ich eine Exception werfen möchte, auch wenn ich zu viele Parameter zur Verfügung stelle, deshalb würde ich die Anzahl der Platzhalter benötigen. – urgas9

Antwort

4

Sie könnten dies mit einem regulären Ausdruck tun, der das Format eines Platzhalters definiert, um die Gesamtzahl der Übereinstimmungen in Ihrem String zu zählen.

// %[argument_index$][flags][width][.precision][t]conversion 
String formatSpecifier 
    = "%(\\d+\\$)?([-#+ 0,(\\<]*)?(\\d+)?(\\.\\d+)?([tT])?([a-zA-Z%])"; 
// The pattern that defines a placeholder 
Pattern pattern = Pattern.compile(formatSpecifier); 
// The String to test 
String[] values = { 
    "%d of %d", 
    "This is my %s", 
    "A simple content.", 
    "This is 100%", "Hi! My name is %s and I have %d dogs and a %d cats." 
}; 
// Iterate over the Strings to test 
for (String value : values) { 
    // Build the matcher for a given String 
    Matcher matcher = pattern.matcher(value); 
    // Count the total amount of matches in the String 
    int counter = 0; 
    while (matcher.find()) { 
     counter++; 
    } 
    // Print the result 
    System.out.printf("%s=%d%n", value, counter); 
} 

Ausgang:

%d of %d=2 
This is my %s=1 
A simple content.=0 
This is 100%=0 
Hi! My name is %s and I have %d dogs and a %d cats.=3 
2

ich den Code von String.format() angepasst haben. Hier ist das Ergebnis:

private static final String formatSpecifier 
    = "%(\\d+\\$)?([-#+ 0,(\\<]*)?(\\d+)?(\\.\\d+)?([tT])?([a-zA-Z%])"; 

private static Pattern fsPattern = Pattern.compile(formatSpecifier); 

private static int parse(String s) { 
    int count = 0; 
    Matcher m = fsPattern.matcher(s); 
    for (int i = 0, len = s.length(); i < len;) { 
    if (m.find(i)) { 
     // Anything between the start of the string and the beginning 
     // of the format specifier is either fixed text or contains 
     // an invalid format string. 
     if (m.start() != i) { 
     // Make sure we didn't miss any invalid format specifiers 
     checkText(s, i, m.start()); 
     // Assume previous characters were fixed text 
     } 

     count++; 
     i = m.end(); 
    } else { 
     // No more valid format specifiers. Check for possible invalid 
     // format specifiers. 
     checkText(s, i, len); 
     // The rest of the string is fixed text 
     break; 
    } 
    } 
    return count; 
} 

private static void checkText(String s, int start, int end) { 
    for (int i = start; i < end; i++) { 
    // Any '%' found in the region starts an invalid format specifier. 
    if (s.charAt(i) == '%') { 
     char c = (i == end - 1) ? '%' : s.charAt(i + 1); 
     throw new UnknownFormatConversionException(String.valueOf(c)); 
    } 
    } 
} 

Test:

public static void main(String[] args) { 
    System.out.println(parse("Hello %s, My name is %s. I am %d years old.")); 
} 

Ausgang: