Guia para java.util.Formatter

Guia para java.util.Formatter

1. Visão geral

Neste artigo, discutiremos a formataçãoString em Java usando a classejava.util.Formatter, que fornece suporte para a justificação e alinhamento do layout.

2. Como usar oFormatter

Lembre-se de C'sprintf? Formatar umString em Java é muito semelhante.

O métodoformat() deFormatter é exposto por meio de um método estático da classeString. Este método aceita um templateString e uma lista de argumentos para preencher o template com:

String greetings = String.format(
  "Hello Folks, welcome to %s !",
  "example");

OString resultante é:

"Hello Folks, welcome to example !"

Um modelo é umString que contém algum texto estático e um ou mais especificadores de formato, que indicam qual argumento deve ser colocado na posição específica.

Neste caso,there’s a single format specifier %s, which gets replaced by the corresponding argument.

3. Especificadores de formato

3.1. Sintaxe geral

A sintaxe dos especificadores de formato para o tipoGeneral, Character,eNumeric é:

%[argument_index$][flags][width][.precision]conversion

Os especificadoresargument_index, flag, width eprecision são opcionais.

  • A parteargument_index é um inteiroi - indicando que o argumentoith da lista de argumentos deve ser usado aqui

  • flags é um conjunto de caracteres usados ​​para modificar o formato de saída

  • width é um número inteiro positivo que indica o número mínimo de caracteres a serem gravados na saída

  • precision é um número inteiro normalmente usado para restringir o número de caracteres, cujo comportamento específico depende da conversão

  • é a parte obrigatória. É um caractere que indica como o argumento deve ser formatado. O conjunto de conversões válidas para um determinado argumento depende do tipo de dados do argumento

Em nosso exemplo acima, se quisermos especificar o número de um argumento explicitamente, podemos escrevê-lo usando os índices de argumento1$e2$.

Ambos sendo o primeiro e o segundo argumento, respectivamente:

String greetings = String.format(
  "Hello %2$s, welcome to %1$s !",
  "example",
  "Folks");

3.2. Para representação deDate/Time

%[argument_index$][flags][width]conversion

Novamente,argument_index, flags ewidth são opcionais.

Vamos dar um exemplo para entender isso:

@Test
public void whenFormatSpecifierForCalendar_thenGotExpected() {
    Calendar c = new GregorianCalendar(2017, 11, 10);
    String s = String.format(
      "The date is: %tm %1$te,%1$tY", c);

    assertEquals("The date is: 12 10,2017", s);
}

Aqui, para cada especificador de formato, o primeiro argumento será usado, portanto,1$. Aqui, se pularmosargument_index para o segundo e terceiro especificador de formato, ele tentará encontrar 3 argumentos, mas precisamos usar o mesmo argumento para todos os 3 especificadores de formato.

Então, está tudo bem se não especificarmosargument _index para o primeiro, mas precisamos especificá-lo para os outros dois.

Oflag aqui é composto de dois caracteres. Onde o primeiro caractere é sempre um‘t' ou‘T'. O segundo caractere depende de qual parte deCalendar deve ser exibida.

Em nosso exemplo, os primeiros especificadores de formatotm indicam o mês formatado com dois dígitos,te indica o dia do mês etY indica o ano formatado com quatro dígitos.

3.3. Especificadores de formato sem argumentos

%[flags][width]conversion

Osflagsewidth opcionais são os mesmos definidos nas seções acima.

Oconversion necessário é um caractere ouString que indica o conteúdo a ser inserido na saída. Atualmente, apenas‘%'e nova linha‘n' podem ser impressos usando este:

@Test
public void whenNoArguments_thenExpected() {
    String s = String.format("John scored 90%% in Fall semester");

    assertEquals("John scored 90% in Fall semester", s);
}

Dentro deformat(), se quisermos imprimir‘%' - precisamos escapar usando‘%%'.

4. Conversões

Vamos agora nos aprofundar em todos os detalhes da sintaxe do especificador de formato, começando comconversion. Observe que você pode encontrar todos os detalhes emFormatter javadocs.

Como observamos nos exemplos acima, a parteconversion é necessária em todos os especificadores de formato e pode ser dividida em várias categorias.

Vamos dar uma olhada em cada um, usando exemplos.

4.1. Geral

Usado para qualquer tipo de argumento. As conversões gerais são:

  1. ‘b’ ou‘B' - para valoresBoolean

  2. ‘h’ ou‘H' - paraHashCode

  3. ‘s' ou‘S' - paraString, senull, imprime “nulo”, senãoarg.toString()

Agora, tentaremos exibir os valoresbooleaneString, usando as conversões correspondentes:

@Test
public void givenString_whenGeneralConversion_thenConvertedString() {
    String s = String.format("The correct answer is %s", false);
    assertEquals("The correct answer is false", s);

    s = String.format("The correct answer is %b", null);
    assertEquals("The correct answer is false", s);

    s = String.format("The correct answer is %B", true);
    assertEquals("The correct answer is TRUE", s);
}

4.2. Personagem

Usado para os tipos básicos que representam caracteres Unicode:char, Character, byte, Byte, short,eShort. Essa conversão também pode ser usada para os tiposinteInteger quandoCharacter.isValidCodePoint(int) retornatrue para eles.

Ele pode ser escrito como‘c’ ou’C’ com base no caso que desejamos.

Vamos tentar imprimir alguns caracteres:

@Test
public void givenString_whenCharConversion_thenConvertedString() {
    String s = String.format("The correct answer is %c", 'a');
    assertEquals("The correct answer is a", s);

    s = String.format("The correct answer is %c", null);
    assertEquals("The correct answer is null", s);

    s = String.format("The correct answer is %C", 'b');
    assertEquals("The correct answer is B", s);

    s = String.format("The valid unicode character: %c", 0x0400);
    assertTrue(Character.isValidCodePoint(0x0400));
    assertEquals("The valid unicode character: Ѐ", s);
}

Vamos dar mais um exemplo de um ponto de código inválido:

@Test(expected = IllegalFormatCodePointException.class)
public void whenIllegalCodePointForConversion_thenError() {
    String s = String.format("The valid unicode character: %c", 0x11FFFF);

    assertFalse(Character.isValidCodePoint(0x11FFFF));
    assertEquals("The valid unicode character: Ā", s);
}

4.3. Numérico - Integrante

Eles são usados ​​para tipos integrais Java:byte, Byte, short, Short, inteInteger, long, Long,eBigInteger. Existem três conversões nesta categoria:

  1. ‘d' - para número decimal

  2. ‘o' - para número octal

  3. ‘X' ou‘x' - para número hexadecimal

Vamos tentar imprimir cada um deles:

@Test
public void whenNumericIntegralConversion_thenConvertedString() {
    String s = String.format("The number 25 in decimal = %d", 25);
    assertEquals("The number 25 in decimal = 25", s);

    s = String.format("The number 25 in octal = %o", 25);
    assertEquals("The number 25 in octal = 31", s);

    s = String.format("The number 25 in hexadecimal = %x", 25);
    assertEquals("The number 25 in hexadecimal = 19", s);
}

4.4. Numérico - Ponto Flutuante

Usado para tipos de ponto flutuante Java:float, Float, double, Double, eBigDecimal

  1. ‘e' ou‘E' formatado como um número decimal em notação científica computadorizada

  2. ‘f' formatado como um número decimal

  3. ‘g' ou‘G' com base no valor de precisão após o arredondamento, esta conversão formata em notação científica computadorizada ou formato decimal

Vamos tentar imprimir os números de ponto flutuante:

@Test
public void whenNumericFloatingConversion_thenConvertedString() {
    String s = String.format(
      "The computerized scientific format of 10000.00 "
      + "= %e", 10000.00);

    assertEquals(
      "The computerized scientific format of 10000.00 = 1.000000e+04", s);

    String s2 = String.format("The decimal format of 10.019 = %f", 10.019);
    assertEquals("The decimal format of 10.019 = 10.019000", s2);
}

4.5. Outras Conversões

  • Date/Time - para tipos Java que são capazes de codificar uma data ou hora:long, Long, Calendar,DateeTemporalAccessor. Para isso, precisamos usar o prefixo‘t' ou‘T', como vimos anteriormente

  • Percent - imprime um‘%' (‘%') literal

  • Line Separator - imprime um separador de linha específico da plataforma

Vamos dar uma olhada em um exemplo simples:

@Test
public void whenLineSeparatorConversion_thenConvertedString() {
    String s = String.format("First Line %nSecond Line");

    assertEquals("First Line \n" + "Second Line", s);
}

5. Bandeiras

Os sinalizadores, em geral, são usados ​​para formatar a saída. Considerando que, no caso de data e hora, eles são usados ​​para especificar qual parte da data deve ser exibida, como vimos no exemplo da Seção 4.

Estão disponíveis vários sinalizadores, cuja lista pode ser encontrada na documentação.

Vamos ver um exemplo de sinalizador para entender seu uso. ‘-‘ é usado para formatar a saída justificada à esquerda:

@Test
public void whenSpecifyFlag_thenGotFormattedString() {
    String s = String.format("Without left justified flag: %5d", 25);
    assertEquals("Without left justified flag:    25", s);

    s = String.format("With left justified flag: %-5d", 25);
    assertEquals("With left justified flag: 25   ", s);
}

6. Precisão

Para conversões gerais,precision is just the maximum number of characters to be written to the output. Considerando que, para as conversões de ponto flutuante, a precisão é o número de dígitos após o ponto de raiz.

A primeira declaração é um exemplo de precisão com números de ponto flutuante e a segunda com conversões gerais:

@Test
public void whenSpecifyPrecision_thenGotExpected() {
    String s = String.format(
      "Output of 25.09878 with Precision 2: %.2f", 25.09878);

    assertEquals("Output of 25.09878 with Precision 2: 25.10", s);

    String s2 = String.format(
      "Output of general conversion type with Precision 2: %.2b", true);

    assertEquals("Output of general conversion type with Precision 2: tr", s2);
}

7. Índice de Argumento

Conforme mencionado anteriormente, oargument_index is an integer that indicates the position of the argument in the argument list. 1$ indica o primeiro argumento,2$ o segundo argumento e assim por diante.

Além disso, há outra maneira de fazer referência a argumentos por posição, usando o sinalizador‘<‘ (‘<'), o que significa que o argumento do especificador de formato anterior será reutilizado. Por exemplo, essas duas instruções produziriam a saída idêntica:

@Test
public void whenSpecifyArgumentIndex_thenGotExpected() {
    Calendar c = Calendar.getInstance();
    String s = String.format("The date is: %tm %1$te,%1$tY", c);
    assertEquals("The date is: 12 10,2017", s);

    s = String.format("The date is: %tm %

8. Outras maneiras de usarFormatter

Até agora vimos o uso do métodoformat() da classeFormatter. Também podemos criar uma instânciaFormatter e usá-la para invocar o métodoformat().

We can create an instance by passing in an Appendable, OutputStream, File or file name. Com base nisso, oString formatado é armazenado emAppendable,OutputStream,File respectivamente.

Vejamos um exemplo de como usá-lo com umAppendable.. Podemos usá-lo com outros da mesma maneira.

8.1. UsandoFormatter comAppendable

Vamos criar uma instância StringBuildersb e criar umFormatter usando-a. Em seguida, invocaremosformat() para formatar umString:

@Test
public void whenCreateFormatter_thenFormatterWithAppendable() {
    StringBuilder sb = new StringBuilder();
    Formatter formatter = new Formatter(sb);
    formatter.format("I am writting to a %s Instance.", sb.getClass());

    assertEquals(
      "I am writting to a class java.lang.StringBuilder Instance.",
      sb.toString());
}

9. Conclusão

Neste artigo, vimos as facilidades de formatação fornecidas pela classejava.util.Formatter. Vimos várias sintaxes que podem ser usadas para formatarStringe os tipos de conversão que podem ser usados ​​para diferentes tipos de dados.

Como de costume, o código dos exemplos que vimos pode ser encontradoover on Github.