如何在Java中格式化字符串

简单的问题,但是我如何格式化字符串

“{2}的{1}步”

用Java代替变量?用c#很简单。

319844 次浏览

看看String.format。但是请注意,它的格式说明符类似于C的printf系列函数——例如:

String.format("Hello %s, %d", "world", 42);

会返回"Hello world, 42"在学习格式说明符时,你可能会发现很有用。Andy Thomas-Cramer好心地在下面的评论中留下了链接,这似乎指向了官方规范。最常用的是:

  • %s -插入一个字符串
  • %d -插入有符号整数(十进制)
  • 插入一个实数,标准表示法

这与c#完全不同,c#使用带有可选格式说明符的位置引用。这意味着你不能做这样的事情:

String.format("The {0} is repeated again: {0}", "word");

... 而不需要重复传递给printf/format的参数。(见下面The Scrum Meister的评论)


如果你只想直接打印结果,你可以找到System.out.printf (PrintStream.printf)来满足你的要求。

如果您选择不使用String。格式,另一个选项是+二进制运算符

String str = "Step " + a + " of " + b;

这相当于

new StringBuilder("Step ").append(String.valueOf(1)).append(" of ").append(String.valueOf(2));

你用哪一种都是你的选择。StringBuilder更快,但速度差异很小。我更喜欢使用+操作符(它执行StringBuilder.append(String.valueOf(X)))操作,并且发现它更容易阅读。

除了字符串。格式,也看一下java.text.MessageFormat。格式不那么简洁,更接近于您提供的c#示例,您也可以使用它进行解析。

例如:

int someNumber = 42;
String someString = "foobar";
Object[] args = {new Long(someNumber), someString};
MessageFormat fmt = new MessageFormat("String is \"{1}\", number is {0}.");
System.out.println(fmt.format(args));

一个更好的例子利用了Java 1.5中的可变参数和自动装箱的改进,并将上面的代码转换为一行代码:

MessageFormat.format("String is \"{1}\", number is {0}.", 42, "foobar");

MessageFormat对于带有choice修饰符的i18nized复数来说稍微好一点。要指定一条消息,当变量为1时正确地使用单数形式,否则使用复数形式,您可以这样做:

String formatString = "there were {0} {0,choice,0#objects|1#object|1<objects}";
MessageFormat fmt = new MessageFormat(formatString);
fmt.format(new Object[] { new Long(numberOfObjects) });
public class StringFormat {


public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
System.out.println("================================");
for(int i=0;i<3;i++){
String s1=sc.next();
int x=sc.nextInt();
System.out.println(String.format("%-15s%03d",s1,x));
}
System.out.println("================================");


}
}
< p > outpot "================================"< br > ved15space123 ved15space123 ved15space123 "================================

Java解决方案

  • “-”用于左缩进

  • “15”使得字符串的最小长度为15

  • “s”(在%后面几个字符)将被我们的String替换
  • 0在整数的左边加上0
  • 3使整数的最小长度为3

我写了一个简单的方法:

public class SomeCommons {
/** Message Format like 'Some String {0} / {1}' with arguments */
public static String msgFormat(String s, Object... args) {
return new MessageFormat(s).format(args);
}
}

所以你可以这样使用它:

SomeCommons.msfgFormat("Step {1} of {2}", 1 , "two");

这个解决方案对我很有效。我需要动态地为REST客户端创建url,所以我创建了这个方法,所以你只需要像这样传递restURL

/customer/{0}/user/{1}/order

并添加尽可能多的参数:

public String createURL (String restURL, Object ... params) {
return new MessageFormat(restURL).format(params);
}

你只需要像这样调用这个方法:

createURL("/customer/{0}/user/{1}/order", 123, 321);

输出

“用户/客户/ 123 / / 321 /秩序”

我写了这个函数,它做了正确的事情。用同名变量的值插入以$开头的单词。

private static String interpol1(String x){
Field[] ffield =  Main.class.getDeclaredFields();
String[] test = x.split(" ") ;
for (String v : test ) {
for ( Field n: ffield ) {
if(v.startsWith("$") && ( n.getName().equals(v.substring(1))  )){
try {
x = x.replace("$" + v.substring(1), String.valueOf( n.get(null)));
}catch (Exception e){
System.out.println("");
}
}
}
}
return x;
}

字符串#格式

格式化字符串最常用的方法是使用这个静态方法,它从Java 5开始就有了,有两个重载方法:

该方法易于使用,并且format模式由底层的格式化程序定义。

String step1 = "one";
String step2 = "two";


// results in "Step one of two"
String string = String.format("Step %s of %s", step1, step2);

你可以传递一个Locale来尊重语言和区域规范。更多信息请参考这个答案:https://stackoverflow.com/a/6431949/3764965 (credit to 马丁Tornwall)。

MessageFormat

MessageFormat类在Java的第一个版本中就可用了,适合国际化。在最简单的形式中,有一个用于格式化的静态方法:

String step1 = "one";
String step2 = "two";


// results in "Step one of two"
String string = MessageFormat.format("Step {0} of {1}", step1, step2);

记住,MessageFormat遵循与String#format不同的特定模式,更多细节请参阅它的JavaDoc: MessageFormat -模式

可以使用Locale,但是,必须实例化类的对象并将其传递给构造函数,因为上面的静态方法使用带有默认语言环境的默认构造函数。更多信息请参考这个答案:https://stackoverflow.com/a/6432100/3764965 (credit to ataylor)。

非标准JDK解决方案

有很多方法可以使用外部库来格式化字符串。如果仅仅为了String格式化的目的而导入库,那么它们几乎没有任何好处。一些例子:

您可以随意添加更多内容,但是,我认为没有理由进一步展开这一节。

Java 15以来的替代方案

从Java 15开始,有一个新的实例方法叫做String#formatted(Object... args)

内部实现与String#format(String format, Object... args)相同。

使用此字符串作为格式字符串的格式,以及提供的参数。

String step1 = "one";
String step2 = "two";


// results in "Step one of two"
String string = "Step %s of %s".formatted(step1, step2);

优势:区别在于该方法不是static,格式化模式是字符串本身,基于args创建一个新模式。这允许链接首先构建格式本身。

缺点: Locale没有重载方法,因此使用默认方法。如果你需要使用自定义Locale,你必须坚持使用String#format(Locale l, String format, Object... args)

Apache Commons Text中的org.apache.commons.text.StringSubstitutor helper类提供了命名变量替换

Map<String, String> valuesMap = new HashMap<>();
valuesMap.put("animal", "quick brown fox");
valuesMap.put("target", "lazy dog");
String resolved = new StringSubstitutor(valuesMap).replace("The ${animal} jumped over the ${target}.");
System.out.println(resolved); // The quick brown fox jumped over the lazy dog.

Apache Commons StringSubstitutor提供了一种简单易读的方法来使用命名变量格式化__abc1。

import org.apache.commons.text.StringSubstitutor;
// ...
Map<String, String> values = new HashMap<>();
values.put("animal", "quick brown fox");
values.put("target", "lazy dog");
StringSubstitutor sub = new StringSubstitutor(values);
String result = sub.replace("The ${animal} jumped over the ${target}.");
// "The quick brown fox jumped over the lazy dog."

这个类支持为变量提供默认值。

String result = sub.replace("The number is ${undefined.property:-42}.");
// "The number is 42."

要使用递归变量替换,调用setEnableSubstitutionInVariables(true);

Map<String, String> values = new HashMap<>();
values.put("b", "c");
values.put("ac", "Test");
StringSubstitutor sub = new StringSubstitutor(values);
sub.setEnableSubstitutionInVariables(true);
String result = sub.replace("${a${b}}");
// "Test"