2016-05-24 8 views
1

В программе Java я использую строку с функцией Formatter.format(), которую я получаю с сервера. Я не могу быть уверен, что для форматирования String имеет местозаполнитель или допустимое число из них. Если это String не так, как ожидалось, я бы хотел исключить или зарегистрировать его как-то.Получить число заполнителей в Formatter.format() String

На данный момент я не забочусь о том, какие типы заполнителей (String, Integer, ...), я хотел бы просто получить количество ожидаемых параметров для каждой строки.

Что такое самый простой способ достичь этого? Один из способов - использовать регулярное выражение, но я думаю, что есть что-то более удобное - например, встроенная функция.

Вот некоторые примеры:

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() бросает исключение, если не обеспечены достаточным количеством параметров. Есть вероятность, что я получу строку без заполнителей. В этом случае, даже если я предоставляю параметры (будет опущен), исключение не будет выбрано (хотя я бы хотел его выбросить), только то, что будет возвращено значение String. Мне нужно сообщить об ошибке на сервер.

+0

Каким образом это может быть "не то, что вы ожидаете?" Предположительно, вы знаете количество заполнителей, которые вы ожидаете - можете ли вы просто попробовать форматирование со значениями по умолчанию и посмотреть, не сработает ли он? –

+0

Я не знаю о встроенной функции, но моя первая мысль - это регулярное выражение. Есть ли у вас какие-либо проблемы с использованием regex? – Hill

+0

@ AndyTurner Я не был достаточно ясен. Я знаю, что метод format генерирует исключение, если я не предоставляю достаточно параметров. Моя проблема в том, что я хотел бы исключить исключение, даже если я предоставляю слишком много параметров, поэтому мне понадобится количество заполнителей. – urgas9

ответ

4

Вы можете сделать это с помощью регулярного выражения, которое определяет формат заполнителя для подсчета общего количества совпадений в вашей строке.

// %[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); 
} 

Выход:

%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

Я приспособил код String.format(). Вот результат:

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

Тест:

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

Выход: