2016-05-24 7 views
1

Javaプログラムでは、サーバから取得するFormatter.format()関数のStringを使用しています。 Stringにはプレースホルダまたは有効な数の文字列が含まれているとは確信できません。 Stringが期待どおりでない場合は、例外をスローしたいと思います。Formatter.format()のプレースホルダーの数を取得するString

この時点では、どのタイプのプレースホルダーが(、Integer、...)であるか気にせず、各文字列に期待されるパラメータの数を取得したいだけです。

これを達成する最も簡単な方法は何ですか? 1つの方法は、正規表現を使用することができますが、私は、より便利な何かがあると思っています - たとえば、組み込みの関数です。ここ

は、いくつかの例は、次のとおり

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

私は組み込み関数についてはわかりませんが、私の最初の考えは正規表現です。正規表現の使用に関する特定の懸念はありますか? – 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.")); 
} 

出力:

関連する問題