Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/315.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 获取Formatter.format()字符串中的占位符数_Java_String_String Formatting_Formatter_String.format - Fatal编程技术网

Java 获取Formatter.format()字符串中的占位符数

Java 获取Formatter.format()字符串中的占位符数,java,string,string-formatting,formatter,string.format,Java,String,String Formatting,Formatter,String.format,在Java程序中,我使用了一个字符串和函数,这是我从服务器获得的。我无法确定要格式化的String是否有占位符或占位符的有效数目。如果字符串不符合预期,我会抛出一个异常,或者以某种方式记录它 此时,我不关心占位符的类型(String,Integer,…),我只想获得每个字符串的预期参数数 最简单的方法是什么?一种方法是使用正则表达式,但我在想是否有更方便的方法——比如内置函数 以下是一些例子: Example String | number of placeholders: %d of %d

在Java程序中,我使用了一个字符串和函数,这是我从服务器获得的。我无法确定要格式化的
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
编辑:
如果提供的参数不足,Formatter.format()将引发异常。有一种可能是我得到一个没有占位符的字符串。在这种情况下,即使我提供了参数(将被省略),也不会抛出异常(尽管我想抛出一个),只会返回字符串值。我需要向服务器报告错误。

您可以使用一个正则表达式来完成此操作,该正则表达式定义占位符的格式,以计算字符串中的匹配总数

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

我已经修改了
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));
    }
  }
}
输出:

三,


以什么方式可以“不是你所期望的”?想必你知道你期望的占位符的数量——你能试着用默认值格式化,看看是否失败吗?我不知道内置函数是什么,但我的第一个想法是regex是可行的。你对使用正则表达式有什么特别的担心吗?@AndyTurner我还不够清楚。我知道如果我没有提供足够的参数,format方法会引发异常。我的问题是,即使我提供了太多的参数,我也会抛出一个异常,这就是为什么我需要占位符的数量。因此,请尝试使用除一个默认值以外的所有默认值进行格式化。如果失败,则有正确数量的占位符;如果成功,占位符就太少了。@Hill实际上不是,但内置函数在各种情况下都经过测试,因此编写自己的正则表达式可能会产生额外的错误。我认为这是它应该具备的功能
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."));
}