Gerar Strings de comprimento fixo preenchidos com espaços em branco

95

Eu preciso produzir uma string de comprimento fixo para gerar um arquivo baseado em posição de caractere. Os caracteres ausentes devem ser preenchidos com caractere de espaço.

Como exemplo, o campo CITY tem um comprimento fixo de 15 caracteres. Para as entradas "Chicago" e "Rio de Janeiro" as saídas são

"Chicago"
" Rio de Janeiro"
.

Rafael Borja
fonte
esta é a resposta correta stackoverflow.com/a/38110257/2642478
Xan

Respostas:

122

Desde Java 1.5, podemos usar o método java.lang.String.format (String, Object ...) e usar o formato semelhante ao printf.

A string de formato "%1$15s"faz o trabalho. Onde 1$indica o índice do argumento, sindica que o argumento é uma String e 15representa a largura mínima da String. Juntando tudo: "%1$15s".

Para um método geral, temos:

public static String fixedLengthString(String string, int length) {
    return String.format("%1$"+length+ "s", string);
}

Talvez alguém possa sugerir outra string de formato para preencher os espaços vazios com um caractere específico?

Rafael Borja
fonte
2
Maybe someone can suggest another format string to fill the empty spaces with an specific character?- dê uma olhada na resposta que dei.
mike
5
De acordo com docs.oracle.com/javase/tutorial/essential/io/formatting.html , 1$representa o índice do argumento e 15a largura
Dmitry Minkovsky
1
Isso não limitará a string ao comprimento 15. Se for mais longa, a saída produzida também será maior do que 15
misterti
1
@misterti uma string.substring limitaria a 15 caracteres. Atenciosamente
Rafael Borja
1
Eu deveria ter mencionado isso, sim. Mas o objetivo do meu comentário foi alertar sobre a possibilidade de uma produção maior do que o desejado, o que poderia ser um problema para campos de comprimento fixo
misterti
55

Utilize String.formato preenchimento de com espaços e substitua-os pelo caractere desejado.

String toPad = "Apple";
String padded = String.format("%8s", toPad).replace(' ', '0');
System.out.println(padded);

Impressões 000Apple.


Atualização de versão mais performant (já que não depende de String.format), que não tem problema de espaços (obrigado a Rafael Borja pela dica).

int width = 10;
char fill = '0';

String toPad = "New York";
String padded = new String(new char[width - toPad.length()]).replace('\0', fill) + toPad;
System.out.println(padded);

Impressões 00New York.

Mas uma verificação precisa ser adicionada para evitar a tentativa de criar uma matriz char com comprimento negativo.

Mike
fonte
O código atualizado funcionará muito bem. Era isso que eu esperava @thanks mike
sudharsan chandrasekaran
27

Este código terá exatamente a quantidade de caracteres fornecida; preenchido com espaços ou truncado no lado direito:

private String leftpad(String text, int length) {
    return String.format("%" + length + "." + length + "s", text);
}

private String rightpad(String text, int length) {
    return String.format("%-" + length + "." + length + "s", text);
}
Kurt Huwig
fonte
12

Você também pode escrever um método simples como abaixo

public static String padString(String str, int leng) {
        for (int i = str.length(); i <= leng; i++)
            str += " ";
        return str;
    }
Yashpal Singla
fonte
8
Esta definitivamente não é a resposta com melhor desempenho. Como as strings são imutáveis ​​em Java, você está essencialmente gerando N novas strings na memória com comprimento igual a str.length + 1 e, portanto, é um desperdício enorme. Uma solução muito melhor seria realizar apenas uma concatenação de string, independentemente do comprimento da string de entrada, e utilizar StringBuilder ou alguma outra forma mais eficiente de conatenação de string no loop for.
anon58192932
12

Para o pad certo você precisa String.format("%0$-15s", str)

ou seja, o -sinal irá para o painel "direito" e nenhum -sinal irá para o painel "esquerdo"

veja meu exemplo aqui

http://pastebin.com/w6Z5QhnJ

a entrada deve ser uma string e um número

exemplo de entrada: Google 1

Bui Dinh Ngoc
fonte
10
import org.apache.commons.lang3.StringUtils;

String stringToPad = "10";
int maxPadLength = 10;
String paddingCharacter = " ";

StringUtils.leftPad(stringToPad, maxPadLength, paddingCharacter)

Muito melhor do que goiaba. Nunca vi um único projeto Java corporativo que usa Guava, mas Apache String Utils é incrivelmente comum.

anon58192932
fonte
6

Aqui está um truque legal:

// E.g pad("sss","00000000"); should deliver "00000sss".
public static String pad(String string, String pad) {
  /*
   * Add the pad to the left of string then take as many characters from the right 
   * that is the same length as the pad.
   * This would normally mean starting my substring at 
   * pad.length() + string.length() - pad.length() but obviously the pad.length()'s 
   * cancel.
   *
   * 00000000sss
   *    ^ ----- Cut before this character - pos = 8 + 3 - 8 = 3
   */
  return (pad + string).substring(string.length());
}

public static void main(String[] args) throws InterruptedException {
  try {
    System.out.println("Pad 'Hello' with '          ' produces: '"+pad("Hello","          ")+"'");
    // Prints: Pad 'Hello' with '          ' produces: '     Hello'
  } catch (Exception e) {
    e.printStackTrace();
  }
}
OldCurmudgeon
fonte
3

Aqui está o código com casos de teste;):

@Test
public void testNullStringShouldReturnStringWithSpaces() throws Exception {
    String fixedString = writeAtFixedLength(null, 5);
    assertEquals(fixedString, "     ");
}

@Test
public void testEmptyStringReturnStringWithSpaces() throws Exception {
    String fixedString = writeAtFixedLength("", 5);
    assertEquals(fixedString, "     ");
}

@Test
public void testShortString_ReturnSameStringPlusSpaces() throws Exception {
    String fixedString = writeAtFixedLength("aa", 5);
    assertEquals(fixedString, "aa   ");
}

@Test
public void testLongStringShouldBeCut() throws Exception {
    String fixedString = writeAtFixedLength("aaaaaaaaaa", 5);
    assertEquals(fixedString, "aaaaa");
}


private String writeAtFixedLength(String pString, int lenght) {
    if (pString != null && !pString.isEmpty()){
        return getStringAtFixedLength(pString, lenght);
    }else{
        return completeWithWhiteSpaces("", lenght);
    }
}

private String getStringAtFixedLength(String pString, int lenght) {
    if(lenght < pString.length()){
        return pString.substring(0, lenght);
    }else{
        return completeWithWhiteSpaces(pString, lenght - pString.length());
    }
}

private String completeWithWhiteSpaces(String pString, int lenght) {
    for (int i=0; i<lenght; i++)
        pString += " ";
    return pString;
}

Eu gosto de TDD;)

Palgaz
fonte
2
String.format("%15s",s) // pads right
String.format("%-15s",s) // pads left

Ótimo resumo aqui

JGFMK
fonte
1

Este código funciona muito bem. Saída esperada

  String ItemNameSpacing = new String(new char[10 - masterPojos.get(i).getName().length()]).replace('\0', ' ');
  printData +=  masterPojos.get(i).getName()+ "" + ItemNameSpacing + ":   " + masterPojos.get(i).getItemQty() +" "+ masterPojos.get(i).getItemMeasure() + "\n";

Happy Coding !!

Sudharsan Chandrasekaran
fonte
0
public static String padString(String word, int length) {
    String newWord = word;
    for(int count = word.length(); count < length; count++) {
        newWord = " " + newWord;
    }
    return newWord;
}
hack4greatness
fonte
0

Esta função simples funciona para mim:

public static String leftPad(String string, int length, String pad) {
      return pad.repeat(length - string.length()) + string;
    }

Invocação:

String s = leftPad(myString, 10, "0");
WvdHooven
fonte