Java 中的 Sprintf 等价物

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/47045/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 07:36:15  来源:igfitidea点击:

Sprintf equivalent in Java

javastringformatting

提问by paperhorse

Printf got added to Java with the 1.5 release but I can't seem to find how to send the output to a string rather than a file (which is what sprintf does in C). Does anyone know how to do this?

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

采纳答案by Eugene Yokota

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

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

See formatand its syntax

查看格式及其语法

回答by FlySwat

Strings are immutable types. You cannot modify them, only return new string instances.

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

Because of that, formatting with an instance method makes little sense, as it would have to be called like:

因此,使用实例方法进行格式化毫无意义,因为它必须像这样调用:

String formatted = "%s: %s".format(key, value);

The original Java authors (and .NET authors) decided that a static method made more sense in this situation, as you are not modifying the target, but instead calling a format method and passing in an input string.

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

Here is an example of why format()would be dumb as an instance method. In .NET (and probably in Java), Replace()is an instance method.

这是一个示例,说明为什么format()将其作为实例方法是愚蠢的。在 .NET(也可能在 Java)中,Replace()是一个实例方法。

You can do this:

你可以这样做:

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

However, nothing happens, because strings are immutable. Replace()tries to return a new string, but it is assigned to nothing.

然而,什么也没有发生,因为字符串是不可变的。Replace()试图返回一个新的字符串,但它没有被赋值。

This causes lots of common rookie mistakes like:

这会导致许多常见的新手错误,例如:

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

Again, nothing happens, instead you have to do:

同样,没有任何反应,而是您必须执行以下操作:

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

Now, if you understand that strings are immutable, that makes perfect sense. If you don't, then you are just confused. The proper place for Replace()would be where format()is, as a static method of String:

现在,如果你明白字符串是不可变的,那就完全有道理了。如果你不这样做,那么你只是感到困惑。适当的地方Replace()是 where format()is,作为 的静态方法String

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

Now there is no question as to what's going on.

现在毫无疑问发生了什么。

The real question is, why did the authors of these frameworks decide that one should be an instance method, and the other static? In my opinion, both are more elegantly expressed as static methods.

真正的问题是,为什么这些框架的作者决定一个应该是实例方法,另一个应该是静态的?在我看来,两者都更优雅地表示为静态方法。

Regardless of your opinion, the truth is that you are less prone to make a mistake using the static version, and the code is easier to understand (No Hidden Gotchas).

不管您的意见如何,事实是使用静态版本更不容易出错,并且代码更容易理解(No Hidden Gotchas)。

Of course there are some methods that are perfect as instance methods, take String.Length()

当然也有一些方法是完美的作为实例方法,拿 String.Length()

int length = "123".Length();

In this situation, it's obvious we are not trying to modify "123", we are just inspecting it, and returning its length. This is a perfect candidate for an instance method.

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

My simple rules for Instance Methods on Immutable Objects:

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

  • If you need to return a new instance of the same type, use a static method.
  • Otherwise, use an instance method.
  • 如果需要返回相同类型的新实例,请使用静态方法。
  • 否则,使用实例方法。

回答by догонят

Both solutions workto simulate printf, but in a different way. For instance, to convert a value to a hex string, you have the 2 following solutions:

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

  • with format(), closest to 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;
    }
    
  • with replace(char oldchar , char newchar), somewhat faster but pretty limited:

        ...
        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)));
        ...
    
  • There is a third solution consisting of just adding the char to retone by one (char are numbers that add to each other!) such as in:

    ...
    ret += HexChars.charAt((int) ((v >> 12) & 0x0f)));
    ret += HexChars.charAt((int) ((v >>  8) & 0x0f)));
    ...
    
  • 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)));
        ...
    
  • 还有包括刚刚加入炭第三解决方案ret由一个一个(字符是数字彼此相加!),如:

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

...but that'd be reallyugly.

……但那真的很难看。

回答by armagedescu

You can do a printf to anything that is an OutputStream with a PrintStream. Somehow like this, printing into a string stream:

您可以对任何带有 PrintStream 的 OutputStream 执行 printf。以某种方式打印到字符串流中:

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

The string stream can be created like this ByteArrayOutputStream:

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

ByteArrayOutputStream baos = new ByteArrayOutputStream();