Existe-t-il un moyen simple de remplir les chaînes en Java?
Cela semble être quelque chose qui devrait être dans une API de type StringUtil, mais je ne trouve rien qui fasse cela.
Existe-t-il un moyen simple de remplir les chaînes en Java?
Cela semble être quelque chose qui devrait être dans une API de type StringUtil, mais je ne trouve rien qui fasse cela.
Réponses:
Apache StringUtils
a plusieurs méthodes: leftPad
, rightPad
, center
et repeat
.
Mais veuillez noter que - comme d'autres l'ont mentionné et démontré dans cette réponse - String.format()
et les Formatter
classes du JDK sont de meilleures options. Utilisez-les sur le code commun.
Depuis Java 1.5, String.format()
peut être utilisé pour remplir à gauche / droite une chaîne donnée.
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) + "*");
}
Et la sortie est:
Howto *
Howto*
1$
? @leo a fait une réponse très similaire qui n'utilise pas 1$
et qui a apparemment le même effet. Est-ce que cela fait une différence?
Rembourrage à 10 caractères:
String.format("%10s", "foo").replace(' ', '*');
String.format("%-10s", "bar").replace(' ', '*');
String.format("%10s", "longer than 10 chars").replace(' ', '*');
production:
*******foo
bar*******
longer*than*10*chars
Afficher '*' pour les caractères du mot de passe:
String password = "secret123";
String padded = String.format("%"+password.length()+"s", "").replace(' ', '*');
la sortie a la même longueur que la chaîne de mot de passe:
secret123
*********
.replace(' ', '*')
était plutôt destiné à montrer l'effet du rembourrage. L'expression masquant le mot de passe n'a pas ce problème de toute façon ... Pour une meilleure réponse sur la personnalisation de la chaîne de remplissage gauche et droite en utilisant la fonctionnalité Java native, voir mon autre réponse.
String.format("%30s", "pad left").replaceAll("(?<=( |^)) ", "*")
ouString.format("%-30s", "pad right").replaceAll(" (?=( |$))", "*")
À la goyave , c'est facile:
Strings.padStart("string", 10, ' ');
Strings.padEnd("string", 10, ' ');
Quelque chose de simple:
La valeur doit être une chaîne. le convertir en chaîne, si ce n'est pas le cas. Comme "" + 123
ouInteger.toString(123)
// let's assume value holds the String we want to pad
String value = "123";
La sous-chaîne commence à partir de l'indice de longueur de la valeur de la valeur jusqu'à la longueur de fin du remplissage:
String padded="00000000".substring(value.length()) + value;
// now padded is "00000123"
Plus précis
pad droit:
String padded = value + ("ABCDEFGH".substring(value.length()));
// now padded is "123DEFGH"
pad gauche:
String padString = "ABCDEFGH";
String padded = (padString.substring(0, padString.length() - value.length())) + value;
// now padded is "ABCDE123"
Jetez un oeil à org.apache.commons.lang.StringUtils#rightPad(String str, int size, char padChar)
.
Mais l'algorithme est très simple (pad jusqu'à la taille des caractères):
public String pad(String str, int size, char padChar)
{
StringBuffer padded = new StringBuffer(str);
while (padded.length() < size)
{
padded.append(padChar);
}
return padded.toString();
}
Outre Apache Commons, voyez également String.format
qui devrait être capable de prendre en charge le remplissage simple (par exemple avec des espaces).
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
, c'est donc correct.
(length - str.length())
est 0
? Le formateur lance un FormatFlagsConversionMismatchException
quand %0s
est la chaîne de format.
Cela m'a pris un peu de temps pour comprendre. La vraie clé est de lire cette documentation 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);
Je sais que ce fil est un peu ancien et la question d'origine était pour une solution facile, mais s'il est censé être très rapide, vous devez utiliser un tableau de caractères.
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 solution de formateur n'est pas optimale. la construction de la chaîne de formatage crée 2 nouvelles chaînes.
La solution d'Apache peut être améliorée en initialisant le sb avec la taille cible afin de remplacer ci-dessous
StringBuffer padded = new StringBuffer(str);
avec
StringBuffer padded = new StringBuffer(pad);
padded.append(value);
empêcherait le tampon interne du sb de croître.
StringBuffer
vous ne pouvez pas accéder à plusieurs threads à la fois (ce qui est vrai dans ce cas), vous devez utiliser un StringBuilder
(dans JDK1.5 +) pour éviter la surcharge de synchronisation.
Voici une autre façon de vous déplacer vers la droite:
// 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-------";
Depuis Java 11, String.repeat (int) peut être utilisé pour remplir à gauche / droite une chaîne donnée.
System.out.println("*".repeat(5)+"apple");
System.out.println("apple"+"*".repeat(5));
Production:
*****apple
apple*****
Vous pouvez réduire la surcharge par appel en conservant les données de remplissage, plutôt que de les reconstruire à chaque fois:
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);
}
}
Vous pouvez également faire de la longueur du résultat un paramètre de la pad(...)
méthode. Dans ce cas, ajustez le remplissage masqué dans cette méthode plutôt que dans le constructeur.
(Astuce: pour un crédit supplémentaire, rendez-le thread-safe! ;-)
Pad avec zéros:
String.format("|%020d|", 93); // prints: |00000000000000000093|
vous pouvez utiliser les méthodes intégrées StringBuilder append () et insert (), pour le remplissage de longueurs de chaîne variables:
AbstractStringBuilder append(CharSequence s, int start, int end) ;
Par exemple:
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());
Cela marche:
"".format("%1$-" + 9 + "s", "XXX").replaceAll(" ", "0")
Il remplira votre chaîne XXX jusqu'à 9 caractères avec un espace. Après cela, tous les espaces blancs seront remplacés par un 0. Vous pouvez changer l'espace blanc et le 0 en ce que vous voulez ...
static
méthode as String.format(…)
au lieu d'abuser d'une chaîne vide. L'enregistrement de quatre caractères dans le code source ne vaut certainement pas la perte de lisibilité.
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 "";
}
Permettez-moi de laisser une réponse pour certains cas que vous devez donner un remplissage gauche / droite (ou une chaîne de préfixe / suffixe ou des espaces) avant de concaténer une autre chaîne et vous ne voulez pas tester la longueur ou toute condition if.
De même pour la réponse choisie, je préférerais StringUtils
Apache Commons mais en utilisant cette façon:
StringUtils.defaultString(StringUtils.leftPad(myString, 1))
Explique:
myString
: la chaîne que j'entre, peut être nulleStringUtils.leftPad(myString, 1)
: si la chaîne est nulle, cette instruction retournerait aussi nulldefaultString
pour donner une chaîne vide pour éviter de concaténer nullLes réponses de @ck et @Marlon Tarak sont les seules à utiliser a char[]
, ce qui est la meilleure approche pour les applications qui ont plusieurs appels aux méthodes de remplissage par seconde. Cependant, ils ne profitent d'aucune optimisation de manipulation de tableau et sont un peu écrasés à mon goût; cela peut être fait sans boucles du tout .
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éthode d'essai 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));
}
Les sorties:
012345678901234567890123456789
cats
cats
cats
cats$$$$$$$$$$$$$$$$$$$$$$$$$$
too long for your own good, buddy
getChars
pour laisser la String
copie de son contenu directement dans le out
tableau, au lieu d'appeler source.toCharArray()
, suivi de System.arraycopy
. J'envisagerais même de simplifier la mise en œuvre pour 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);
; bien que cela semble fill
faire plus de travail, cela permet en fait à la JVM d'éliminer le remplissage par défaut.
java.util.Formatter
fera un rembourrage gauche et droit. Pas besoin de dépendances étranges de tiers (voudriez-vous les ajouter pour quelque chose de si trivial).
[J'ai laissé de côté les détails et créé cet article «wiki communautaire» car ce n'est pas quelque chose dont j'ai besoin.]
Toutes les opérations de chaîne doivent généralement être très efficaces , en particulier si vous travaillez avec de grands ensembles de données. Je voulais quelque chose de rapide et flexible, similaire à ce que vous obtiendrez dans la commande plsql pad. De plus, je ne veux pas inclure une énorme bibliothèque pour juste une petite chose. Avec ces considérations, aucune de ces solutions n'était satisfaisante. Ce sont les solutions que j'ai trouvées, qui ont eu les meilleurs résultats d'analyse comparative, si quelqu'un peut l'améliorer, veuillez ajouter votre commentaire.
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;
}
}
Utilisez cette fonction.
private String leftPadding(String word, int length, char ch) {
return (length > word.length()) ? leftPadding(ch + word, length, ch) : word;
}
comment utiliser?
leftPadding(month, 2, '0');
sortie: 01 02 03 04 .. 11 12
Beaucoup de gens ont des techniques très intéressantes mais j'aime rester simple donc je vais avec ceci:
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();
}
Une solution simple sans aucune API sera la suivante:
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 Java, pas de bibliothèque de fantaisie.
// 6 characters padding example
String pad = "******";
// testcases for 0, 4, 8 characters
String input = "" | "abcd" | "abcdefgh"
Pad gauche, ne pas limiter
result = pad.substring(Math.min(input.length(),pad.length())) + input;
results: "******" | "**abcd" | "abcdefgh"
Pad Right, ne pas limiter
result = input + pad.substring(Math.min(input.length(),pad.length()));
results: "******" | "abcd**" | "abcdefgh"
Pad gauche, limite à la longueur du pad
result = (pad + input).substring(input.length(), input.length() + pad.length());
results: "******" | "**abcd" | "cdefgh"
Pad Right, limite à la longueur du pad
result = (input + pad).substring(0, pad.length());
results: "******" | "abcd**" | "abcdef"
Que diriez-vous d'utiliser la récursivité? La solution donnée ci-dessous est compatible avec toutes les versions JDK et aucune bibliothèque externe requise :)
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);
}
}
REMARQUE : Cette solution ajoutera le remplissage, avec un petit ajustement, vous pouvez préfixer la valeur du tampon.
Voici une version parallèle pour ceux d'entre vous qui ont de très longues cordes :-)
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));
Exemples de remplissage en goyave:
Exemples de remplissage dans Apache Commons:
Exemples de remplissage dans JDK:
Une solution simple serait:
package nl;
public class Padder {
public static void main(String[] args) {
String s = "123" ;
System.out.println("#"+(" " + s).substring(s.length())+"#");
}
}