如何在Java中格式化字符串

kat*_*tit 169 java string string-formatting

原始问题,但我如何格式化这样的字符串:

"{2}的步骤{1}"

通过使用Java替换变量?在C#中很容易.

Mar*_*all 217

看看String.format.但是请注意,它需要格式说明符类似于C的printf函数族 - 例如:

String.format("Hello %s, %d", "world", 42);
Run Code Online (Sandbox Code Playgroud)

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

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

这与C#完全不同,后者使用带有可选格式说明符的位置引用.这意味着你不能做以下事情:

String.format("The {0} is repeated again: {0}", "word");
Run Code Online (Sandbox Code Playgroud)

... 没有实际重复传递给printf/format的参数.(参见Scrum Meister的评论如下)


如果您只想直接打印结果,可以根据自己的喜好找到System.out.printf(PrintStream.printf).

  • `String.format`也可以取数字位置:`String.format("%2 $ s%1 $ s","foo","bar");`将输出`bar foo` (47认同)
  • 从 Java 15 开始,可以使用 [String.formatted()](https://docs.oracle.com/en/java/javase/17/docs/api/java.base) 直接在字符串上使用 String.format /java/lang/String.html#formatted(java.lang.Object...))。`"你好%s,%d".formatted("world", 42)` (10认同)
  • 另一个选项是java.text.MessageFormat,它接受{1}样式格式符号.String.format()的格式符号可以类似于C的printf()格式符号 - 但也可以不同.有关完整语法,请参阅http://download.oracle.com/javase/6/docs/api/java/util/Formatter.html#syntax. (2认同)

ata*_*lor 136

除了String.format之外,还可以看看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));
Run Code Online (Sandbox Code Playgroud)

一个更好的例子利用了Java 1.5中的varargs和autoboxing改进,并将上述内容转化为单行:

MessageFormat.format("String is \"{1}\", number is {0}.", 42, "foobar");
Run Code Online (Sandbox Code Playgroud)

MessageFormat使用选择修饰符进行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) });
Run Code Online (Sandbox Code Playgroud)

  • MessageFormat用于本地化,因此在使用时要小心.例如,以下代码`MessageFormat.format("Number {0}",1234));`取决于默认语言环境,可以生成`Number 1,234`而不是`Number 1234`. (17认同)

Tom*_*ski 6

我为它写了一个简单的方法:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

所以你可以用它作为:

SomeCommons.msfgFormat("Step {1} of {2}", 1 , "two");
Run Code Online (Sandbox Code Playgroud)


Rya*_*mos 5

如果选择不使用String.format,则另一个选项是+二进制运算符

String str = "Step " + a + " of " + b;
Run Code Online (Sandbox Code Playgroud)

这相当于

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

您选择使用哪种。StringBuilder更快,但速度差异很小。我更喜欢使用+运算符(执行a StringBuilder.append(String.valueOf(X)))并发现它更易于阅读。

  • 1)针对字符串格式的问题,向您解释`+`运算符的工作方式。2)您的解释甚至不准确。“ +”等效于使用“ StringBuilder”,而不是“ String.concat”。[(有关这方面的过多信息。)](http://www.znetdevelopment.com/blogs/2009/04/06/java-string-concatenation/) (10认同)
  • 如果您要否认我,请解释原因。 (4认同)
  • 实际上是StringBuilder.append。我将更新答案。 (2认同)

Ved*_*ash 5

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("================================");

    }
}
Run Code Online (Sandbox Code Playgroud)

outpot"================================"
ved15space123 ved15space123 ved15space123"=========== =====================

Java解决方案

  • " - "用于左缩进

  • "15"使String的最小长度为15

  • "s"(%之后的几个字符)将被我们的String替换
  • 0填充我们的整数,左边是0
  • 3使得整数的最小长度为3


Nik*_*las 5

爪哇 15

String::formatted(Object... args)从 Java 15 开始,有一个名为的新实例方法。

内部实现与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);     
Run Code Online (Sandbox Code Playgroud)

优点:不同之处在于该方法不是static,并且格式化模式是一个字符串本身,基于args. 这允许链接首先构建格式本身。

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


mer*_*nst 5

JEP 430:字符串模板(预览)

您可以使用 Java 的字符串模板功能。它在JEP 430中进行了描述,并作为预览功能出现在 JDK 21 中。

这是一个使用示例:

String name = "Joan";
String info = STR."My name is \{name}";
assert info.equals("My name is Joan");   // true
Run Code Online (Sandbox Code Playgroud)

与其他语言(例如 C# 的字符串插值和 Python 的 f 字符串)中的功能相比,Java 的字符串模板更加通用且安全得多。例如,字符串连接或插值使得 SQL 注入攻击成为可能:

String query = "SELECT * FROM Person p WHERE p.last_name = '" + name + "'";
ResultSet rs = conn.createStatement().executeQuery(query);
Run Code Online (Sandbox Code Playgroud)

但这个变体(来自 JEP 430)可以防止 SQL 注入:

PreparedStatement ps = DB."SELECT * FROM Person p WHERE p.last_name = \{name}";
ResultSet rs = ps.executeQuery();
Run Code Online (Sandbox Code Playgroud)