Эквивалент Sprintf в Java

Printf добавлен в Java с выпуском версии 1.5, но я не могу найти способ отправки вывода в строку, а не в файл (что и делает sprintf на C). Кто-нибудь знает как это сделать?

Ответ 1

// 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

Ответ 2

@erickson.

Строки - это неизменные типы. Вы не можете их изменять, только возвращаете новые экземпляры строк.

Из-за этого "foo".format() имеет мало смысла, поскольку его нужно было бы называть как

string newString = "foo".format();

Оригинальные авторы java (и авторы .NET) решили, что статический метод имеет больше смысла в этой ситуации, поскольку вы не изменяете "foo", а вместо этого вызываете метод format и передаете входную строку.

EDIT: Хех, этот сайт может быть настолько забавным иногда. Я получил downvoted за упоминание того факта, что строки являются неизменяемыми типами.

Вот пример того, почему 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");

Теперь нет вопроса о том, что происходит.

Реальный вопрос: почему авторы этих фреймворков решили, что нужно быть методом экземпляра, а другим статическим? На мой взгляд, оба они более элегантно выражаются как статические методы, но, похоже, эриксон считает, что оба они являются экземплярами методов.

Независимо от вашего мнения, правда в том, что вы менее склонны ошибаться, используя статическую версию, и код легче понять (No Hidden Gotchas).

Конечно, есть некоторые методы, которые идеально подходят как методы экземпляра, берут String.Length()

int length = "123".Length();

В этой ситуации очевидно, что мы не пытаемся изменить "123", мы просто проверяем его и возвращаем его длину... Это идеальный кандидат для метода экземпляра.

Мои простые правила для методов экземпляра на неизменяемых объектах:

  • Если вам нужно вернуть новый экземпляр того же типа, используйте статический метод.
  • В противном случае используйте метод экземпляра.

Ответ 3

Оба решения работают для моделирования 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)));
    ...
    

... но это будет действительно уродливо.

Ответ 4

Вы можете сделать printf для всего, что является OutputStream с PrintStream. Как-то так, печать в потоке строки:

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