我正在尝试使用MessageFormat
类在java中格式化String。 String包含位置字段,但只有在我提供字段编号时才有效。例如
MessageFormat.format("{0} {1}", "Hi", "Java")
有效,但
MessageFormat.format("{} {}", "Hi", "Java")
给出了
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)
有没有办法(任何其他类或库),它可以处理像python那样的自动和手动字段编号?
In [3]: print "{} {}".format("Hi", "Java")
Hi Java
In [4]: print "{0} {1}".format("Hi", "Java")
Hi Java
答案 0 :(得分:3)
您可以执行以下操作:
String.format("{} {}".replace("{}", "%s"), new String[]{"Hi", "Java"}));
它首先用{}
替换%s
,然后将每个%s
替换为您提供的String数组中的相应值作为format
方法的参数。
请注意,由于format
接受Object... args
作为第二个参数,您可以写:
String.format("{} {}".replace("{}", "%s"), "Hi", "Java");
答案 1 :(得分:2)
听起来像String.format()
就是你想要的。
String foo = String.format("%s %s", "Hi", "Java")
StringBuffer bar = new StringBuffer(foo);
答案 2 :(得分:1)
我使用slf4j进行日志记录,这使您能够记录如下字符串:
LoggerFactory.getLogger("name").debug("{} {}", "Hello", "World");
刚看了一下源代码,看看用于格式化字符串的内容,它使用了这个类:
org.slf4j.helpers.MessageFormatter
这里有3种方法可供选择。 1替换单个对象:
MessageFormatter.format(String message, Object arg);
替换2个物体:
MessageFormatter.format(String message, Object arg1, Object arg2);
用一个替换对象数组:
MessageFormatter.arrayFormat(String message, Object[] argArray);
这些都返回FormattingTuple
类型的对象。要从对象获取格式化字符串,您应该调用FormattingTuple.getMessage();
要将其与手动字段编号一起使用,请查看以下方法:
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();
}
答案 3 :(得分:1)
添加到@JohnH答案,String.format可以自动和手动字段索引来格式化String。
String.format("%s %s", "Hi", "Java")
String.format("%1$s %2$s %1$s", "Hi", "Java")
它不符合"{1} {2}"
的人体工程学,但可以完成工作。
答案 4 :(得分:1)
如果我被限制在像barunsthakur这样的标准库中,我会使用Maroun Maroun发布的模式。
除了使用索引参数手动准备字符串之外,Ben Greens聪明的想法对于使用非索引参数进行日志记录时使用sfl4j的每个人都很有用。
对我来说有一个缺点: 我现在可以使用索引和非索引参数,但是我无法使用java.text.MessageFormat.format()中的FormatType和FormatStyle选项,例如{0,数字,货币}。
所以我编写了Ben的解决方案的扩展版本,该解决方案利用了所有3种变体。
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();
}
}
}
单元测试:
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);