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.
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.
Risposte:
Apache StringUtils
ha diversi metodi: leftPad
, rightPad
, center
e repeat
.
Ma tieni presente che - come altri hanno già detto e dimostrato in questa risposta - String.format()
e le Formatter
classi nel JDK sono opzioni migliori. Usali sul codice comune.
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*
1$
? @leo ha fatto una risposta molto simile che non usa 1$
e apparentemente ha lo stesso effetto. Fa la differenza?
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
*********
.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.
String.format("%30s", "pad left").replaceAll("(?<=( |^)) ", "*")
oppureString.format("%-30s", "pad right").replaceAll(" (?=( |$))", "*")
In Guava , questo è facile:
Strings.padStart("string", 10, ' ');
Strings.padEnd("string", 10, ' ');
Qualcosa di semplice:
Il valore dovrebbe essere una stringa. convertilo in stringa, se non lo è. Come "" + 123
oInteger.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"
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();
}
Oltre ad Apache Commons, vedi anche String.format
quali dovrebbero essere in grado di occuparsi di semplici imbottiture (ad es. Con spazi).
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
, quindi questo è corretto.
(length - str.length())
è 0
? Il formatter genera un FormatFlagsConversionMismatchException
quando %0s
è la stringa di formato.
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);
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.
StringBuffer
non è 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.
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-------";
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*****
È 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! ;-)
Ho trovato questo su Dzone
Pad con zeri:
String.format("|%020d|", 93); // prints: |00000000000000000093|
è 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());
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 ...
static
metodo String.format(…)
invece di abusare di una stringa vuota. Salvare quattro caratteri nel codice sorgente sicuramente non vale la perdita di leggibilità.
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 "";
}
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' StringUtils
Apache Commons ma usando in questo modo:
StringUtils.defaultString(StringUtils.leftPad(myString, 1))
Spiegare:
myString
: la stringa che inserisco, può essere nullaStringUtils.leftPad(myString, 1)
: se string è null, anche questa istruzione restituirà nulldefaultString
per fornire una stringa vuota per impedire null concatenatoLe 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
getChars
per consentire alla String
copia il suo contenuto direttamente out
nell'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 fill
farebbe più lavoro, in realtà consente alla JVM di eliminare il riempimento zero predefinito.
java.util.Formatter
farà 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.]
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;
}
}
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
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();
}
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();
}
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"
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.
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));
Esempi di imbottitura in Guava:
Esempi di imbottitura in Apache Commons:
Esempi di imbottitura in JDK:
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())+"#");
}
}