Sprintf相当于Java

时间:2008-09-05 23:05:35

标签: java string formatting

Printf在1.5版本中被添加到Java中,但我似乎无法找到如何将输出发送到字符串而不是文件(这是sprintf在C中所做的)。有谁知道如何做到这一点?

5 个答案:

答案 0 :(得分:456)

// Store the formatted string in 'result'
String result = String.format("%4d", i * j);

// Write the result to standard output
System.out.println( result );

请参阅format及其syntax

答案 1 :(得分:25)

@erickson。

字符串是不可变类型。您无法修改它们,只返回新的字符串实例。

因此,“foo”.format()没什么意义,因为它必须被称为

string newString = "foo".format();

最初的java作者(和.NET作者)认为静态方法在这种情况下更有意义,因为你不是修改“foo”,而是调用格式方法并传入输入字符串。

编辑:嘿,这个网站有时候会很有趣。我因为提到字符串是不可变类型这一事实而被投票。

这是一个为什么Format()作为实例方法变得愚蠢的例子。在.NET(可能还有Java)中,Replace()是一种实例方法。

你可以这样做:

 "I Like Wine".Replace("Wine","Beer");

但是,没有任何反应,因为字符串是不可变的。替换尝试返回一个新字符串,但它被分配给任何内容。

这导致许多常见的菜鸟错误,如:

// Contrived Example
inputText.Replace(" ","%20");

同样,没有任何事情发生,而你必须这样做:

inputText = inputText.Replace(" ","%20");

现在,如果您了解字符串是不可变的,那就非常有意义了。如果你不这样做,那你就困惑了。 Replace的适当位置是Format的位置,作为String的静态方法:

 inputText = String.Replace(inputText," ", "%20");

现在毫无疑问,最新情况如何。

真正的问题是,为什么这些框架的作者决定一个应该是一个实例方法,另一个是静态的?在我看来,两者都更优雅地表达为静态方法,但erickson似乎认为它们都属于实例方法。

无论您的意见如何,事实是您不太容易使用静态版本出错,并且代码更容易理解(没有隐藏的问题)。

当然有一些方法是完美的实例方法,采用String.Length()

int length = "123".Length();

在这种情况下,很明显我们不是要修改“123”,我们只是检查它,并返回它的长度......这是实例方法的完美候选。

我对不可变对象的实例方法的简单规则:

  • 如果需要返回相同类型的新实例,请使用静态方法。
  • 否则,请使用实例方法。

答案 2 :(得分:2)

两种解决方案都可以模拟printf,但方式不同。 例如,要将值转换为十六进制字符串,您可以使用以下两种解决方案:

  • format(),最接近sprintf()

    final static String HexChars = "0123456789abcdef";
    
    public static String getHexQuad(long v) {
        String ret;
        if(v > 0xffff) ret = getHexQuad(v >> 16); else ret = "";
        ret += String.format("%c%c%c%c",
            HexChars.charAt((int) ((v >> 12) & 0x0f)),
            HexChars.charAt((int) ((v >>  8) & 0x0f)),
            HexChars.charAt((int) ((v >>  4) & 0x0f)),
            HexChars.charAt((int) ( v        & 0x0f)));
        return ret;
    }
    
  • replace(char oldchar , char newchar),有点快但很有限:

        ...
        ret += "ABCD".
            replace('A', HexChars.charAt((int) ((v >> 12) & 0x0f))).
            replace('B', HexChars.charAt((int) ((v >>  8) & 0x0f))).
            replace('C', HexChars.charAt((int) ((v >>  4) & 0x0f))).
            replace('D', HexChars.charAt((int) ( v        & 0x0f)));
        ...
    
  • 还有第三个解决方案,只需将char逐个添加到ret(char是相互添加的数字!),例如:

    ...
    ret += HexChars.charAt((int) ((v >> 12) & 0x0f)));
    ret += HexChars.charAt((int) ((v >>  8) & 0x0f)));
    ...
    

...但真的丑陋。

答案 3 :(得分:0)

您可以对带有PrintStream的OutputStream进行任何处理。 这样,打印到字符串流中:

PrintStream ps = new PrintStream(baos);
ps.printf("there is a %s from %d %s", "hello", 3, "friends");
System.out.println(baos.toString());
baos.reset(); //need reset to write new string
ps.printf("there is a %s from %d %s", "flip", 5, "haters");
System.out.println(baos.toString());
baos.reset();

可以像这样的ByteArrayOutputStream创建字符串流:

ByteArrayOutputStream baos = new ByteArrayOutputStream();

答案 4 :(得分:0)

自Java 13开始,您对String拥有formatted 1方法,该方法与文本块一起作为预览功能2添加。 您可以使用它代替String.format()

Assertions.assertEquals(
   "%s %d %.3f".formatted("foo", 123, 7.89),
   "foo 123 7.890"
);