¿Cómo puedo rellenar una cadena en Java?

432

¿Hay alguna manera fácil de rellenar cadenas en Java?

Parece algo que debería estar en una API similar a StringUtil, pero no puedo encontrar nada que haga esto.

pvgoddijn
fuente
Sobre el tema de la función apache frente al formateador de cadenas hay pocas dudas de que la función apache es más clara y fácil de leer. Ajustar el formateador en nombres de funciones no es ideal.
Terra Caines

Respuestas:

189

Apache StringUtilstiene varios métodos: leftPad, rightPad, centery repeat.

Pero tenga en cuenta que, como otros han mencionado y demostrado en esta respuesta , String.format()y las Formatterclases en el JDK son mejores opciones. Úselos sobre el código común.

GaryF
fuente
9191
java.util.Formatter (y String.format ()) hace esto. Siempre prefiera el JDK a una biblioteca externa si la versión JDK hace el trabajo (lo que hace).
cletus
66
Por varias razones, ahora preferiría Guava a Apache Commons; Esta respuesta muestra cómo hacerlo en Guayaba .
Jonik
1
@ Jonik, ¿te gustaría enumerar algunas de tus razones? Las API se ven más o menos igual.
glen3b
3
@ glen3b: Para una utilidad individual, como estos ayudantes de relleno de cadenas, realmente no importa qué lib usar. Dicho esto, la guayaba es en general una biblioteca más moderna, más limpia y mejor documentada que sus contrapartes en varios proyectos de Apache Commons (Commons Lang, Commons Collections, Commons IO, etc.). También está construido por tipos realmente inteligentes (Kevin Bourrillion et al), muchos de los cuales están activos en SO . Yo mismo terminé reemplazando las diversas librerías de Apache Commons con solo Guava hace años, y no me arrepiento.
Jonik
3
@ glen3b: Algunas buenas lecturas adicionales sobre esta pregunta .
Jonik
635

Desde Java 1.5, String.format()se puede usar para rellenar a la izquierda / derecha una cadena dada.

public static String padRight(String s, int n) {
     return String.format("%-" + n + "s", s);  
}

public static String padLeft(String s, int n) {
    return String.format("%" + n + "s", s);  
}

...

public static void main(String args[]) throws Exception {
 System.out.println(padRight("Howto", 20) + "*");
 System.out.println(padLeft("Howto", 20) + "*");
}

Y la salida es:

Howto               *
               Howto*
RealHowTo
fuente
39
¿Qué pasa si necesita lpad con otros caracteres (no espacios)? ¿Todavía es posible con String.format? No soy capaz de hacer que funcione ...
Guido
66
AFAIK String.format () no puede hacer eso, pero no es demasiado difícil codificarlo, consulte rgagnon.com/javadetails/java-0448.html (segundo ejemplo)
RealHowTo
61
@ Nullw0rm, si te refieres a rgagnon.com, ten en cuenta que RealHowTo también es el autor de rgagnon.com, por lo que se acreditaría a sí mismo ...
Colin Pickard el
3
al menos en mi JVM, el "#" no funciona, el "-" está bien. (Solo borra el #). Esto puede ser consistente con la documentación del formateador, no sé; dice "'#' '\ u0023' Requiere que la salida use un formulario alternativo. La definición del formulario se especifica mediante la conversión".
gatoatigrado
66
Gracias por la increíble respuesta. Sin embargo, tengo una duda, ¿ 1$para qué sirve ? @leo ha hecho una respuesta muy similar que no usa 1$y aparentemente tiene el mismo efecto. ¿Hace alguna diferencia?
Fabrício Matté
257

Relleno a 10 caracteres:

String.format("%10s", "foo").replace(' ', '*');
String.format("%-10s", "bar").replace(' ', '*');
String.format("%10s", "longer than 10 chars").replace(' ', '*');

salida:

  *******foo
  bar*******
  longer*than*10*chars

Muestra '*' para los caracteres de la contraseña:

String password = "secret123";
String padded = String.format("%"+password.length()+"s", "").replace(' ', '*');

la salida tiene la misma longitud que la cadena de contraseña:

  secret123
  *********
León
fuente
50
Siempre y cuando todos recordemos no pasar una cadena con espacios ...: D
leviathanbadger
44
Estoy con @ aboveyou00: esta es una solución horrenda para cadenas con espacios, incluido el ejemplo proporcionado por leo. Una solución para rellenar una cadena a la izquierda o la derecha no debería alterar la cadena de entrada como aparece en la salida, a menos que el relleno original de la cadena de entrada haga que exceda la longitud de relleno especificada.
Brian Warshaw
3
Reconocer la cuestión del espacio. .replace(' ', '*')estaba más bien destinado a mostrar el efecto del relleno. La expresión de ocultación de contraseña no tiene este problema de todos modos ... Para obtener una mejor respuesta sobre la personalización de la cadena de relleno izquierda y derecha utilizando la función nativa de Java, consulte mi otra respuesta.
leo
Si la cadena contiene solo espacios individuales y desea rellenar con diferentes caracteres, puede usar regex replace con mirar hacia atrás / adelante: String.format("%30s", "pad left").replaceAll("(?<=( |^)) ", "*")oString.format("%-30s", "pad right").replaceAll(" (?=( |$))", "*")
Jaroslaw Pawlak
88

En guayaba , esto es fácil:

Strings.padStart("string", 10, ' ');
Strings.padEnd("string", 10, ' ');
Garrett Hall
fuente
33

Algo sencillo:

El valor debe ser una cadena. conviértalo a cadena, si no lo es. Me gusta "" + 123oInteger.toString(123)

// let's assume value holds the String we want to pad
String value = "123";

El inicio de la subcadena desde el índice de caracteres de la longitud del valor hasta la longitud final del relleno:

String padded="00000000".substring(value.length()) + value;

// now padded is "00000123"

Más preciso

almohadilla derecha:

String padded = value + ("ABCDEFGH".substring(value.length())); 

// now padded is "123DEFGH"

almohadilla izquierda:

String padString = "ABCDEFGH";
String padded = (padString.substring(0, padString.length() - value.length())) + value;

// now padded is "ABCDE123"
Shimon Doodkin
fuente
24

Echa un vistazo a org.apache.commons.lang.StringUtils#rightPad(String str, int size, char padChar).

Pero el algoritmo es muy simple (pad hasta caracteres de tamaño):

public String pad(String str, int size, char padChar)
{
  StringBuffer padded = new StringBuffer(str);
  while (padded.length() < size)
  {
    padded.append(padChar);
  }
  return padded.toString();
}
Arne Burmeister
fuente
11
Tenga en cuenta que a partir de Java 1.5 vale la pena usar StringBuilder en lugar de StringBuffer.
Jon Skeet
21

Además de Apache Commons, también vea String.formatcuáles deberían ser capaces de encargarse del relleno simple (por ejemplo, con espacios).

Variable miserable
fuente
17
public static String LPad(String str, Integer length, char car) {
  return (str + String.format("%" + length + "s", "").replace(" ", String.valueOf(car))).substring(0, length);
}

public static String RPad(String str, Integer length, char car) {
  return (String.format("%" + length + "s", "").replace(" ", String.valueOf(car)) + str).substring(str.length(), length + str.length());
}

LPad("Hi", 10, 'R') //gives "RRRRRRRRHi"
RPad("Hi", 10, 'R') //gives "HiRRRRRRRR"
RPad("Hi", 10, ' ') //gives "Hi        "
RPad("Hi", 1, ' ')  //gives "H"
//etc...
Eduardo
fuente
44
Presta atención: invertiste nombres de funciones; si lo ejecutas lo verás.
azulado
Además, si la cadena original contiene espacios, entonces esto no funciona
Steven Shaw
@StevenShaw Si no me equivoco, el reemplazo no está dirigido al original str, por lo que esto es correcto.
mafu
3
Por convención, no debe usar una letra mayúscula para los nombres de las funciones.
principal-ideal-domain
¿Hay una condicional faltante en devolver la cadena como es cuando (length - str.length())es 0? El formateador arroja un FormatFlagsConversionMismatchExceptioncuando %0ses la cadena de formato.
Devin Walters
7

Esto me llevó un tiempo darme cuenta. La clave real es leer la documentación de Formatter.

// Get your data from wherever.
final byte[] data = getData();
// Get the digest engine.
final MessageDigest md5= MessageDigest.getInstance("MD5");
// Send your data through it.
md5.update(data);
// Parse the data as a positive BigInteger.
final BigInteger digest = new BigInteger(1,md5.digest());
// Pad the digest with blanks, 32 wide.
String hex = String.format(
    // See: http://download.oracle.com/javase/1.5.0/docs/api/java/util/Formatter.html
    // Format: %[argument_index$][flags][width]conversion
    // Conversion: 'x', 'X'  integral    The result is formatted as a hexadecimal integer
    "%1$32x",
    digest
);
// Replace the blank padding with 0s.
hex = hex.replace(" ","0");
System.out.println(hex);
Nthalk
fuente
¿Por qué hacer el final tan complicado? Podrías haber hecho String hex = String.format ("% 032x", digest); y tenía exactamente los mismos resultados, sólo que sin una innecesaria replace () y tener que utilizar el acceso a las variables $ específicos (sólo hay una, después de todo.)
ArtOfWarfare
@ArtOfWarfare punto justo. Originalmente, alguien solicitó valores hexadecimales de relleno en otra pregunta, vi que tenía un enlace a la documentación del formateador. Es complicado por lo completo.
Nthalk
6

Sé que este hilo es un poco viejo y la pregunta original era para una solución fácil, pero si se supone que es realmente rápido, debe usar una matriz de caracteres.

public static String pad(String str, int size, char padChar)
{
    if (str.length() < size)
    {
        char[] temp = new char[size];
        int i = 0;

        while (i < str.length())
        {
            temp[i] = str.charAt(i);
            i++;
        }

        while (i < size)
        {
            temp[i] = padChar;
            i++;
        }

        str = new String(temp);
    }

    return str;
}

La solución del formateador no es óptima. solo construir la cadena de formato crea 2 nuevas cadenas.

La solución de Apache se puede mejorar inicializando el SB con el tamaño objetivo, reemplazando a continuación

StringBuffer padded = new StringBuffer(str); 

con

StringBuffer padded = new StringBuffer(pad); 
padded.append(value);

evitaría que el búfer interno del SB crezca.

ck.
fuente
Si StringBufferno se puede acceder a varios subprocesos a la vez (lo que en este caso es cierto), debe usar un StringBuilder(en JDK1.5 +) para evitar la sobrecarga de la sincronización.
glen3b
5

Aquí hay otra forma de desplazarse hacia la derecha:

// put the number of spaces, or any character you like, in your paddedString

String paddedString = "--------------------";

String myStringToBePadded = "I like donuts";

myStringToBePadded = myStringToBePadded + paddedString.substring(myStringToBePadded.length());

//result:
myStringToBePadded = "I like donuts-------";
fawsha1
fuente
5

Desde Java 11, String.repeat (int) se puede usar para rellenar a la izquierda / derecha una cadena dada.

System.out.println("*".repeat(5)+"apple");
System.out.println("apple"+"*".repeat(5));

Salida:

*****apple
apple*****
Eko Setiawan
fuente
1
¡La mejor respuesta para java 11!
Nagy Attila
4

Puede reducir la sobrecarga por llamada reteniendo los datos de relleno, en lugar de reconstruirlos cada vez:

public class RightPadder {

    private int length;
    private String padding;

    public RightPadder(int length, String pad) {
        this.length = length;
        StringBuilder sb = new StringBuilder(pad);
        while (sb.length() < length) {
            sb.append(sb);
        }
        padding = sb.toString();
   }

    public String pad(String s) {
        return (s.length() < length ? s + padding : s).substring(0, length);
    }

}

Como alternativa, puede hacer que la longitud del resultado sea un parámetro para el pad(...)método. En ese caso, realice el ajuste del relleno oculto en ese método en lugar de hacerlo en el constructor.

(Sugerencia: para obtener crédito adicional, ¡haga que sea seguro para subprocesos! ;-)

joel.neely
fuente
1
Eso es seguro para subprocesos, excepto para publicaciones inseguras (haga que sus campos sean finales, como es natural). Creo que el rendimiento podría mejorarse haciendo una subcadena antes del + que debería reemplazarse por concat (curiosamente).
Tom Hawtin - tackline
3

Encontré esto en Dzone

Almohadilla con ceros:

String.format("|%020d|", 93); // prints: |00000000000000000093|
OJVM
fuente
Esta debería ser la respuesta, simple y concisa, sin necesidad de instalar bibliotecas externas.
Wong Jia Hau
2

puede usar los métodos incorporados StringBuilder append () e insert (), para el relleno de longitudes de cadena variables:

AbstractStringBuilder append(CharSequence s, int start, int end) ;

Por ejemplo:

private static final String  MAX_STRING = "                    "; //20 spaces

    Set<StringBuilder> set= new HashSet<StringBuilder>();
    set.add(new StringBuilder("12345678"));
    set.add(new StringBuilder("123456789"));
    set.add(new StringBuilder("1234567811"));
    set.add(new StringBuilder("12345678123"));
    set.add(new StringBuilder("1234567812234"));
    set.add(new StringBuilder("1234567812222"));
    set.add(new StringBuilder("12345678122334"));

    for(StringBuilder padMe: set)
        padMe.append(MAX_STRING, padMe.length(), MAX_STRING.length());
ef_oren
fuente
2

Esto funciona:

"".format("%1$-" + 9 + "s", "XXX").replaceAll(" ", "0")

Llenará su String XXX hasta 9 caracteres con un espacio en blanco. Después de eso, todos los espacios en blanco se reemplazarán con un 0. Puede cambiar el espacio en blanco y el 0 a lo que desee ...

Sebastian S.
fuente
Debe invocar el staticmétodo como en String.format(…)lugar de abusar de una cadena vacía. Guardar cuatro caracteres en el código fuente seguramente no vale la pérdida de legibilidad.
Holger
2
public static String padLeft(String in, int size, char padChar) {                
    if (in.length() <= size) {
        char[] temp = new char[size];
        /* Llenado Array con el padChar*/
        for(int i =0;i<size;i++){
            temp[i]= padChar;
        }
        int posIniTemp = size-in.length();
        for(int i=0;i<in.length();i++){
            temp[posIniTemp]=in.charAt(i);
            posIniTemp++;
        }            
        return new String(temp);
    }
    return "";
}
Marlon Tarax
fuente
2

Permítame dejar una respuesta para algunos casos en los que necesita dar relleno izquierdo / derecho (o cadena o espacios de prefijo / sufijo) antes de concatenar a otra cadena y no desea probar la longitud ni ninguna condición.

Al igual que con la respuesta seleccionada, preferiría el StringUtilsde Apache Commons, pero de esta manera:

StringUtils.defaultString(StringUtils.leftPad(myString, 1))

Explique:

  • myString: la cadena que ingresé, puede ser nula
  • StringUtils.leftPad(myString, 1): si la cadena es nula, esta declaración también devolverá nulo
  • luego use defaultStringpara dar una cadena vacía para evitar concatenar nulo
Osify
fuente
2

Las respuestas de @ck y @Marlon Tarak son las únicas que utilizan a char[], lo que es mejor para las aplicaciones que tienen varias llamadas a métodos de relleno por segundo. Sin embargo, no aprovechan las optimizaciones de manipulación de matriz y están un poco sobrescritos para mi gusto; Esto se puede hacer sin bucles .

public static String pad(String source, char fill, int length, boolean right){
    if(source.length() > length) return source;
    char[] out = new char[length];
    if(right){
        System.arraycopy(source.toCharArray(), 0, out, 0, source.length());
        Arrays.fill(out, source.length(), length, fill);
    }else{
        int sourceOffset = length - source.length();
        System.arraycopy(source.toCharArray(), 0, out, sourceOffset, source.length());
        Arrays.fill(out, 0, sourceOffset, fill);
    }
    return new String(out);
}

Método de prueba simple:

public static void main(String... args){
    System.out.println("012345678901234567890123456789");
    System.out.println(pad("cats", ' ', 30, true));
    System.out.println(pad("cats", ' ', 30, false));
    System.out.println(pad("cats", ' ', 20, false));
    System.out.println(pad("cats", '$', 30, true));
    System.out.println(pad("too long for your own good, buddy", '#', 30, true));
}

Salidas:

012345678901234567890123456789
cats                          
                          cats
                cats
cats$$$$$$$$$$$$$$$$$$$$$$$$$$
too long for your own good, buddy 
ndm13
fuente
1
Puede usar getCharspara permitir que la Stringcopia de su contenido directamente en la outmatriz, en lugar de llamar source.toCharArray(), seguido de System.arraycopy. Incluso consideraría simplificar la implementación a char[] out = new char[length]; Arrays.fill(out, 0, length, fill); source.getChars(0, source.length(), out, right? 0: length - source.length()); return new String(out);; Si bien parece que fillesto haría más trabajo, en realidad permite que la JVM elimine el relleno cero predeterminado.
Holger
1

java.util.Formatterhará relleno izquierdo y derecho. No es necesario contar con dependencias de terceros extrañas (desearía agregarlas para algo tan trivial).

[He omitido los detalles e hice esta publicación 'wiki de la comunidad' ya que no es algo que necesito.]

Tom Hawtin - tackline
fuente
44
Estoy en desacuerdo. En cualquier proyecto de Java más grande, normalmente realizarás tanta manipulación de String que vale la pena usar Apache Commons Lang para mejorar la legibilidad y evitar errores. Todos ustedes conocen códigos como someString.subString (someString.indexOf (startCharacter), someString.lastIndexOf (endCharacter)), que se pueden evitar fácilmente con StringUtils.
Bananeweizen
1

Toda operación de cadena generalmente debe ser muy eficiente , especialmente si está trabajando con grandes conjuntos de datos. Quería algo que fuera rápido y flexible, similar a lo que obtendrás en el comando plsql pad. Además, no quiero incluir una gran lib para una pequeña cosa. Con estas consideraciones, ninguna de estas soluciones fue satisfactoria. Estas son las soluciones que se me ocurrieron, que tuvieron los mejores resultados de evaluación comparativa, si alguien puede mejorarlo, agregue su comentario.

public static char[] lpad(char[] pStringChar, int pTotalLength, char pPad) {
    if (pStringChar.length < pTotalLength) {
        char[] retChar = new char[pTotalLength];
        int padIdx = pTotalLength - pStringChar.length;
        Arrays.fill(retChar, 0, padIdx, pPad);
        System.arraycopy(pStringChar, 0, retChar, padIdx, pStringChar.length);
        return retChar;
    } else {
        return pStringChar;
    }
}
  • tenga en cuenta que se llama con String.toCharArray () y el resultado se puede convertir a String con un nuevo String ((char []) result). La razón de esto es que si aplica varias operaciones, puede hacerlas todas en char [] y no seguir convirtiendo entre formatos: detrás de escena, String se almacena como char []. Si estas operaciones se incluyeran en la clase String, habría sido dos veces más eficiente: velocidad y memoria.
EarlB
fuente
De hecho, esta parece ser la forma más eficiente
David Lilljegren
1

Usa esta función.

private String leftPadding(String word, int length, char ch) {
   return (length > word.length()) ? leftPadding(ch + word, length, ch) : word;
}

¿cómo utilizar?

leftPadding(month, 2, '0');

salida: 01 02 03 04 .. 11 12

Samet ÖZTOPRAK
fuente
1

Mucha gente tiene algunas técnicas muy interesantes, pero me gusta que sea simple, así que sigo con esto:

public static String padRight(String s, int n, char padding){
    StringBuilder builder = new StringBuilder(s.length() + n);
    builder.append(s);
    for(int i = 0; i < n; i++){
        builder.append(padding);
    }
    return builder.toString();
}

public static String padLeft(String s, int n,  char padding) {
    StringBuilder builder = new StringBuilder(s.length() + n);
    for(int i = 0; i < n; i++){
        builder.append(Character.toString(padding));
    }
    return builder.append(s).toString();
}

public static String pad(String s, int n, char padding){
    StringBuilder pad = new StringBuilder(s.length() + n * 2);
    StringBuilder value = new StringBuilder(n);
    for(int i = 0; i < n; i++){
        pad.append(padding);
    }
    return value.append(pad).append(s).append(pad).toString();
}
Aelphaeis
fuente
2
Esto es muy ineficiente, debe usar un StringBuilder
wkarl
Como ya conoce la longitud, debe decirle al StringBuilder que asigne tanto espacio cuando lo instancia.
Ariel
@Ariel interesante que mencionas eso porque solo estaba hablando con alguien más sobre eso hoy jajaja.
Aelphaeis
0

Una solución simple sin ninguna API será la siguiente:

public String pad(String num, int len){
    if(len-num.length() <=0) return num;
    StringBuffer sb = new StringBuffer();
    for(i=0; i<(len-num.length()); i++){
        sb.append("0");
    }
    sb.append(num);
    return sb.toString();
}
Shashank Shekhar
fuente
0

Oneliners de Java, no hay una biblioteca elegante.

// 6 characters padding example
String pad = "******";
// testcases for 0, 4, 8 characters
String input = "" | "abcd" | "abcdefgh"

Pad Left, no limite

result = pad.substring(Math.min(input.length(),pad.length())) + input;
results: "******" | "**abcd" | "abcdefgh"

Pad Right, no limites

result = input + pad.substring(Math.min(input.length(),pad.length()));
results: "******" | "abcd**" | "abcdefgh"

Almohadilla izquierda, límite a la longitud de la almohadilla

result = (pad + input).substring(input.length(), input.length() + pad.length());
results: "******" | "**abcd" | "cdefgh"

Almohadilla derecha, límite a la longitud de la almohadilla

result = (input + pad).substring(0, pad.length());
results: "******" | "abcd**" | "abcdef"
León
fuente
0

¿Qué hay de usar la recursividad? La solución dada a continuación es compatible con todas las versiones de JDK y no requiere bibliotecas externas :)

private static String addPadding(final String str, final int desiredLength, final String padBy) {
        String result = str;
        if (str.length() >= desiredLength) {
            return result;
        } else {
            result += padBy;
            return addPadding(result, desiredLength, padBy);
        }
    }

NOTA : Esta solución agregará el relleno, con un pequeño ajuste puede prefijar el valor del pad.

Saikat
fuente
0

Aquí hay una versión paralela para aquellos de ustedes que tienen cadenas muy largas :-)

int width = 100;
String s = "129018";

CharSequence padded = IntStream.range(0,width)
            .parallel()
            .map(i->i-(width-s.length()))
            .map(i->i<0 ? '0' :s.charAt(i))
            .collect(StringBuilder::new, (sb,c)-> sb.append((char)c), (sb1,sb2)->sb1.append(sb2));
David Lilljegren
fuente
0

Ejemplos de relleno en guayaba:

Ejemplos de relleno en Apache Commons:

Ejemplos de relleno en JDK:

APISonar
fuente
-1

Una solución simple sería:

package nl;
public class Padder {
    public static void main(String[] args) {
        String s = "123" ;
        System.out.println("#"+("     " + s).substring(s.length())+"#");
    }
}
Hans Andeweg
fuente
-1

Cómo es esto

La cadena es "hola" y el relleno requerido es 15 con el pad izquierdo "0"

String ax="Hello";
while(ax.length() < 15) ax="0"+ax;
Satwant
fuente
10
Este genera hasta 15 cadenas nuevas.
claj
@claj Sí, pero esto .
ruffin