Come posso pad una stringa in Java?


432

C'è un modo semplice per riempire le stringhe in Java?

Sembra qualcosa che dovrebbe essere in qualche API simile a StringUtil, ma non riesco a trovare nulla che lo faccia.


Sulla questione della funzione apache rispetto al formattatore di stringhe ci sono pochi dubbi sul fatto che la funzione apache sia più chiara e facile da leggere. Il wrapping del formatter nei nomi delle funzioni non è l'ideale.
Terra Caines,

Risposte:


189

Apache StringUtilsha diversi metodi: leftPad, rightPad, centere repeat.

Ma tieni presente che - come altri hanno già detto e dimostrato in questa risposta - String.format()e le Formatterclassi nel JDK sono opzioni migliori. Usali sul codice comune.


91
java.util.Formatter (e String.format ()) fa questo. Preferisce sempre JDK a una libreria esterna se la versione JDK fa il lavoro (cosa che fa).
cletus,

6
Per diversi motivi, ora preferirei Guava ad Apache Commons; questa risposta mostra come farlo in guava .
Jonik,

1
@Jonik ti andrebbe di elencare alcuni dei tuoi motivi? Le API sembrano praticamente uguali.
glen3b,

3
@ glen3b: per una singola utility, come questi helper di imbottitura di stringhe, non fa davvero alcuna differenza quale lib usare. Detto questo, Guava è nel complesso una lib più moderna, più pulita e meglio documentata rispetto alle sue controparti in vari progetti Apache Commons (Commons Lang, Commons Collections, Commons IO, ecc.). È anche costruito da ragazzi davvero intelligenti (Kevin Bourrillion et al), molti dei quali sono attivi in ​​SO . Io stesso ho finito per sostituire le varie librerie Apache Commons solo con Guava anni fa, e non ho avuto rimpianti.
Jonik,

3
@ glen3b: qualche buona lettura ulteriore a questa domanda .
Jonik,

635

A partire da Java 1.5, String.format()può essere utilizzato per il pad sinistro / destro di una determinata stringa.

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) + "*");
}

E l'output è:

Howto               *
               Howto*

39
Cosa succede se è necessario lpad con altri caratteri (non spazi)? È ancora possibile con String.format? Non sono in grado di farlo funzionare ...
Guido,

6
AFAIK String.format () non può farlo, ma non è troppo difficile codificarlo, vedi rgagnon.com/javadetails/java-0448.html (secondo esempio)
RealHowTo

61
@ Nullw0rm, se ti riferisci a rgagnon.com, tieni presente che anche RealHowTo è l'autore di rgagnon.com, quindi si accrediterebbe da solo ...
Colin Pickard,

3
almeno sulla mia JVM, il "#" non funziona, il "-" va bene. (Basta eliminare il #). Ciò potrebbe essere coerente con la documentazione del formatter, non so; dice "'#' '\ u0023' Richiede che l'output utilizzi un modulo alternativo. La definizione del modulo è specificata dalla conversione."
gatoatigrado,

6
Grazie per la fantastica risposta. Ho un dubbio però, a cosa serve 1$? @leo ha fatto una risposta molto simile che non usa 1$e apparentemente ha lo stesso effetto. Fa la differenza?
Fabrício Matté,

257

Riempimento a 10 caratteri:

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

produzione:

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

Visualizza '*' per i caratteri della password:

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

l'output ha la stessa lunghezza della stringa della password:

  secret123
  *********

50
Finché tutti ricordiamo di non passare una stringa con spazi ...: D
leviathanbadger

4
Sono con @ aboveyou00: questa è una soluzione orrenda per stringhe con spazi, incluso l'esempio fornito da leo. Una soluzione per il riempimento di una stringa a sinistra o a destra non dovrebbe alterare la stringa di input come appare nell'output, a meno che il riempimento originale della stringa di input non le faccia superare la lunghezza di riempimento specificata.
Brian Warshaw,

3
Riconosci il problema dello spazio. .replace(' ', '*')era piuttosto destinato a mostrare l'effetto dell'imbottitura. L'espressione che nasconde la password non presenta questo problema ... Per una risposta migliore sulla personalizzazione della stringa di riempimento sinistra e destra utilizzando la funzione Java nativa, vedere la mia altra risposta.
leo

Se la stringa contiene solo spazi singoli e vuoi riempire con caratteri diversi, puoi usare regex sostituisci con lo sguardo dietro / avanti: String.format("%30s", "pad left").replaceAll("(?<=( |^)) ", "*")oppureString.format("%-30s", "pad right").replaceAll(" (?=( |$))", "*")
Jaroslaw Pawlak,

88

In Guava , questo è facile:

Strings.padStart("string", 10, ' ');
Strings.padEnd("string", 10, ' ');

33

Qualcosa di semplice:

Il valore dovrebbe essere una stringa. convertilo in stringa, se non lo è. Come "" + 123oInteger.toString(123)

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

La sottostringa inizia dall'indice char di lunghezza del valore fino alla lunghezza finale del riempimento:

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

// now padded is "00000123"

Più preciso

pad destro:

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

// now padded is "123DEFGH"

pad sinistro:

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

// now padded is "ABCDE123"

24

Dai un'occhiata org.apache.commons.lang.StringUtils#rightPad(String str, int size, char padChar).

Ma l'algoritmo è molto semplice (pad fino a dimensioni caratteri):

public String pad(String str, int size, char padChar)
{
  StringBuffer padded = new StringBuffer(str);
  while (padded.length() < size)
  {
    padded.append(padChar);
  }
  return padded.toString();
}

11
Si noti che a partire da Java 1.5 vale la pena usare StringBuilder invece di StringBuffer.
Jon Skeet,

21

Oltre ad Apache Commons, vedi anche String.formatquali dovrebbero essere in grado di occuparsi di semplici imbottiture (ad es. Con spazi).


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

4
Presta attenzione: hai invertito i nomi delle funzioni; se lo esegui vedrai.
bluastro

inoltre se lo str originale contiene spazi, allora questo non funziona
Steven Shaw,

@StevenShaw Se non sbaglio, la sostituzione non ha come target l'originale str, quindi questo è corretto.
mafu,

3
Per convenzione non dovresti usare una lettera maiuscola per i nomi delle funzioni.
dominio-principale-ideale

C'è una condizione mancante per restituire la stringa com'è quando (length - str.length())è 0? Il formatter genera un FormatFlagsConversionMismatchExceptionquando %0sè la stringa di formato.
Devin Walters,

7

Mi ci è voluto un po 'di tempo per capire. La vera chiave è leggere quella documentazione di 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);

Perché rendere la fine così complicata? Avresti potuto appena fatto String hex = String.format ("% 032x", digest); e aveva gli stessi esatti risultati, solo senza un inutile rimpiazzo () e dovendo usare $ per accedere a variabili specifiche (dopo tutto ce n'è uno solo)
ArtOfWarfare

@ArtOfWarfare: punto giusto. Qualcuno originariamente ha chiesto di riempire i valori esadecimali in un'altra domanda, ho visto che avevo un link alla documentazione del formatter. È complicato per completezza.
Nthalk,

6

so che questo thread è un po 'vecchio e la domanda originale era per una soluzione semplice ma se si suppone che sia davvero veloce, dovresti usare un array di caratteri.

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 soluzione di formattazione non è ottimale. solo la costruzione della stringa di formato crea 2 nuove stringhe.

La soluzione di apache può essere migliorata inizializzando sb con la dimensione target, quindi sostituendo di seguito

StringBuffer padded = new StringBuffer(str); 

con

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

impedirebbe la crescita del buffer interno dello sb.


Se StringBuffernon è possibile accedere a più thread contemporaneamente (il che in questo caso è vero), è necessario utilizzare un StringBuilder(in JDK1.5 +) per evitare il sovraccarico della sincronizzazione.
glen3b,

5

Ecco un altro modo per spostarsi a destra:

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

5

A partire da Java 11, String.repeat (int) può essere utilizzato per il pad sinistro / destro di una determinata stringa.

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

Produzione:

*****apple
apple*****

1
La migliore risposta per java 11!
Nagy Attila,

4

È possibile ridurre l'overhead per chiamata conservando i dati di riempimento, anziché ricostruendoli ogni volta:

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

}

In alternativa, è possibile rendere la lunghezza del risultato un parametro del pad(...)metodo. In tal caso, esegui la regolazione dell'imbottitura nascosta in quel metodo anziché nel costruttore.

(Suggerimento: per ulteriore credito, rendilo thread-safe! ;-)


1
Questo è thread-safe, ad eccezione della pubblicazione non sicura (rendi i tuoi campi definitivi, ovviamente). Penso che le prestazioni potrebbero essere migliorate facendo una sottostringa prima del + che dovrebbe essere sostituita da concat (abbastanza stranamente).
Tom Hawtin - tackline il

3

Ho trovato questo su Dzone

Pad con zeri:

String.format("|%020d|", 93); // prints: |00000000000000000093|

Questa dovrebbe essere la risposta, semplice e concisa, non è necessario installare librerie esterne.
Wong Jia Hau,

2

è possibile utilizzare i metodi incorporati String () e insert () di StringBuilder, per il riempimento di lunghezze di stringa variabili:

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

Per esempio:

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

2

Questo funziona:

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

Riempirà la tua stringa XXX fino a 9 caratteri con uno spazio bianco. Dopodiché tutti gli spazi bianchi saranno sostituiti con uno 0. Puoi cambiare lo spazio bianco e lo 0 in qualsiasi cosa tu voglia ...


Dovresti invocare il staticmetodo String.format(…)invece di abusare di una stringa vuota. Salvare quattro caratteri nel codice sorgente sicuramente non vale la perdita di leggibilità.
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 "";
}

2

Permettetemi di lasciare una risposta per alcuni casi in cui è necessario fornire il riempimento sinistro / destro (o la stringa o gli spazi prefisso / suffisso) prima di concatenarsi a un'altra stringa e non si desidera verificare la lunghezza o alcuna condizione if.

Lo stesso per la risposta selezionata, preferirei l' StringUtilsApache Commons ma usando in questo modo:

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

Spiegare:

  • myString: la stringa che inserisco, può essere nulla
  • StringUtils.leftPad(myString, 1): se string è null, anche questa istruzione restituirà null
  • quindi utilizzare defaultString per fornire una stringa vuota per impedire null concatenato

2

Le risposte di @ck e @Marlon Tarak sono le uniche a usare a char[], che per le applicazioni che hanno più chiamate ai metodi di riempimento al secondo è l'approccio migliore. Tuttavia, non sfruttano le ottimizzazioni di manipolazione dell'array e sono un po 'sovrascritte per i miei gusti; questo può essere fatto senza loop .

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

Metodo di prova semplice:

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

Uscite:

012345678901234567890123456789
cats                          
                          cats
                cats
cats$$$$$$$$$$$$$$$$$$$$$$$$$$
too long for your own good, buddy 

1
Puoi usare getChars per consentire alla Stringcopia il suo contenuto direttamente outnell'array, anziché chiamare source.toCharArray(), seguito da System.arraycopy. Vorrei anche prendere in considerazione la semplificazione dell'implementazione 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);; mentre questo sembra fillfarebbe più lavoro, in realtà consente alla JVM di eliminare il riempimento zero predefinito.
Holger

1

java.util.Formatterfarà imbottitura sinistra e destra. Non sono necessarie dipendenze di terze parti (vorresti aggiungerle per qualcosa di così banale).

[Ho lasciato fuori i dettagli e ho reso questo post 'community wiki' in quanto non è qualcosa di cui ho bisogno.]


4
Non sono d'accordo. In qualsiasi progetto Java di grandi dimensioni in genere eseguirai così tanta manipolazione di stringhe, che vale la pena di aumentare la leggibilità e la prevenzione degli errori utilizzando Apache Commons Lang. Tutti conoscete codice come someString.subString (someString.indexOf (startCharacter), someString.lastIndexOf (endCharacter)), che può essere facilmente evitato con StringUtils.
Bananeweizen

1

Tutti operazioni sulle stringhe di solito devono essere molto efficienti , specialmente se si lavora con grandi insiemi di dati. Volevo qualcosa che fosse veloce e flessibile, simile a quello che otterrai nel comando plsql pad. Inoltre, non voglio includere un'enorme lib solo per una piccola cosa. Con queste considerazioni nessuna di queste soluzioni è stata soddisfacente. Queste sono le soluzioni che ho trovato, che hanno dato i migliori risultati di benchmarking, se qualcuno può migliorare su di esso, per favore aggiungi il tuo commento.

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;
    }
}
  • nota che viene chiamato con String.toCharArray () e il risultato può essere convertito in String con il nuovo risultato String ((char [])). La ragione di ciò è che se si applicano più operazioni, è possibile eseguirle tutte su char [] e non continuare la conversione tra formati: dietro le quinte, String viene archiviato come char []. Se queste operazioni fossero state incluse nella classe String stessa, sarebbero state due volte più efficienti - in termini di velocità e memoria.

Questo in effetti sembra il modo più efficiente
David Lilljegren,

1

Usa questa funzione

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

come usare?

leftPadding(month, 2, '0');

uscita: 01 02 03 04 .. 11 12


1

Molte persone hanno alcune tecniche molto interessanti ma mi piace mantenerlo semplice, quindi vado con questo:

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

2
Questo è molto inefficiente, dovresti usare StringBuilder
wkarl,

Dato che conosci già la lunghezza, dovresti dire a StringBuilder di allocare molto spazio quando lo installi.
Ariel,

@Ariel interessante che tu lo abbia menzionato perché stavo solo parlando con qualcun altro di quel lol oggi.
Aelphaeis,

0

Una soluzione semplice senza API sarà la seguente:

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

0

Oneliner Java, nessuna libreria di fantasia.

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

Pad sinistro, non limitare

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

Pad Right, non limitare

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

Pad sinistro, limite alla lunghezza del pad

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

Pad destro, limite alla lunghezza del pad

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

0

Che ne dici di usare la ricorsione? La soluzione fornita di seguito è compatibile con tutte le versioni di JDK e non sono necessarie librerie esterne :)

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 : questa soluzione aggiungerà l'imbottitura, con una piccola modifica è possibile aggiungere il valore del pad.


0

Ecco una versione parallela per quelli di voi che hanno stringhe molto lunghe :-)

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

0

-1

Una soluzione semplice sarebbe:

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

-1

Com'è

La stringa è "ciao" e l'imbottitura richiesta è 15 con "0" pad sinistro

String ax="Hello";
while(ax.length() < 15) ax="0"+ax;

10
questo genera fino a 15 nuove stringhe.
Claj,

@claj Sì, ma questo .
ruffin,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.