¿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.
¿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.
Respuestas:
Apache StringUtils
tiene varios métodos: leftPad
, rightPad
, center
y repeat
.
Pero tenga en cuenta que, como otros han mencionado y demostrado en esta respuesta , String.format()
y las Formatter
clases en el JDK son mejores opciones. Úselos sobre el código común.
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*
1$
para qué sirve ? @leo ha hecho una respuesta muy similar que no usa 1$
y aparentemente tiene el mismo efecto. ¿Hace alguna diferencia?
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
*********
.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.
String.format("%30s", "pad left").replaceAll("(?<=( |^)) ", "*")
oString.format("%-30s", "pad right").replaceAll(" (?=( |$))", "*")
En guayaba , esto es fácil:
Strings.padStart("string", 10, ' ');
Strings.padEnd("string", 10, ' ');
Algo sencillo:
El valor debe ser una cadena. conviértalo a cadena, si no lo es. Me gusta "" + 123
oInteger.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"
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();
}
Además de Apache Commons, también vea String.format
cuáles deberían ser capaces de encargarse del relleno simple (por ejemplo, con espacios).
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...
str
, por lo que esto es correcto.
(length - str.length())
es 0
? El formateador arroja un FormatFlagsConversionMismatchException
cuando %0s
es la cadena de formato.
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);
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.
StringBuffer
no 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.
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-------";
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*****
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! ;-)
Encontré esto en Dzone
Almohadilla con ceros:
String.format("|%020d|", 93); // prints: |00000000000000000093|
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());
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 ...
static
mé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.
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 "";
}
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 StringUtils
de Apache Commons, pero de esta manera:
StringUtils.defaultString(StringUtils.leftPad(myString, 1))
Explique:
myString
: la cadena que ingresé, puede ser nulaStringUtils.leftPad(myString, 1)
: si la cadena es nula, esta declaración también devolverá nulodefaultString
para dar una cadena vacía para evitar concatenar nuloLas 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
getChars
para permitir que la String
copia de su contenido directamente en la out
matriz, 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 fill
esto haría más trabajo, en realidad permite que la JVM elimine el relleno cero predeterminado.
java.util.Formatter
hará 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.]
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;
}
}
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
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();
}
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();
}
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"
¿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.
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));
Ejemplos de relleno en guayaba:
Ejemplos de relleno en Apache Commons:
Ejemplos de relleno en JDK:
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())+"#");
}
}