Java'da bir String'i nasıl doldurabilirim?


431

Java'da Dizeleri doldurmanın kolay bir yolu var mı?

Bazı StringUtil benzeri API'de olması gereken bir şey gibi görünüyor, ancak bunu yapan bir şey bulamıyorum.


Apache işlevinin dize biçimlendiricisine karşı olması durumunda, apache işlevinin daha net ve okunması kolay olduğundan şüphe yoktur. Biçimlendiriciyi işlev adlarına sarmak ideal değildir.
Terra Caines

Yanıtlar:


189

Apaçi StringUtilsçeşitli yöntemler vardır: leftPad, rightPad, centerve repeat.

Ancak, diğerlerinin bu cevapta belirttiği ve gösterdiği gibi - String.format()ve FormatterJDK'daki sınıfların daha iyi seçenekler olduğunu lütfen unutmayın . Onları ortak kod üzerinde kullanın.


91
java.util.Formatter (ve String.format ()) bunu yapar. JDK sürümü işi yaparsa, her zaman JDK'yı harici bir kitaplığa tercih edin.
cletus

6
Birkaç nedenden dolayı şimdi Guava'yı Apache Commons'a tercih ediyorum; bu cevap Guava'da nasıl yapılacağını gösterir .
Jonik

1
@Jonik bazı nedenlerinizi listelemek ister misiniz? API'lar hemen hemen aynı görünüyor.
glen3b

3
@ glen3b: Bu string padding yardımcıları gibi bireysel bir yardımcı program için hangi lib'in kullanılacağını gerçekten fark etmez. Bununla birlikte, Guava genel olarak çeşitli Apache Commons projelerindeki (Commons Lang, Commons Koleksiyonları, Commons IO, vb.) Daha modern, daha temiz ve daha iyi belgelenmiş bir lib. Ayrıca, çoğu SO'da aktif olan gerçekten akıllı adamlar (Kevin Bourrillion ve ark.) Tarafından inşa edilmiştir . Kendimi yıllarca çeşitli Apache Commons kütüphanelerini Guava ile değiştirdim ve pişmanlık duymadım.
Jonik

3
@ glen3b: Bu soruda daha iyi okumalar .
Jonik

634

Java 1.5 beri, String.format()belirli bir dizeyi sol / sağ pad için kullanılabilir.

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

Ve çıktı:

Howto               *
               Howto*

39
Diğer karakterlerle (boşluklarla değil) dokunmanız gerekiyorsa ne olur? String.format ile hala mümkün mü? Çalışmasını sağlayamıyorum ...
Guido

6
AFAIK String.format () bunu yapamaz, ancak kodlamak çok zor değildir, bkz. Rgagnon.com/javadetails/java-0448.html (2. örnek)
RealHowTo

61
@ Nullw0rm, rgagnon.com'a atıfta bulunuyorsanız, RealHowTo'nun da rgagnon.com'un yazarı olduğunu unutmayın, bu yüzden kendini kredilendirir ...
Colin Pickard

3
en azından benim JVM, "#" çalışmıyor, "-" iyi. (Sadece # tuşunu silin). Bu biçimlendirici belgeleri ile tutarlı olabilir, bilmiyorum; "'#' '\ u0023' yazıyor Başka bir form kullanılmasını gerektirir. Formun tanımı dönüşüm tarafından belirtilir."
gatoatigrado

6
Müthiş cevap için teşekkürler. Yine de bir şüphem var, ne 1$için? @leo kullanılmayan çok benzer bir cevap verdi 1$ve görünüşe göre aynı etkiye sahip. Bir fark yaratır mı?
Fabrício Matté

257

10 karaktere kadar dolgu:

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

çıktı:

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

Şifre karakterleri için '*' göster:

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

Çıktı şifre dizesiyle aynı uzunlukta:

  secret123
  *********

50
Hepimiz boşluklu bir dizeden
geçmemeyi

4
@ Aboveyou00 ile beraberim - bu leo ​​tarafından sağlanan örnek de dahil olmak üzere, boşluk dizeleri için korkunç bir çözümdür. Bir dizeyi solda veya sağda doldurmak için kullanılan bir çözüm, giriş dizesinin orijinal dolgusu belirtilen dolum uzunluğunu aşmasına neden olmadıkça, giriş dizesini çıktıda göründüğü gibi değiştirmemelidir.
Brian Warshaw

3
Uzay konusunu onaylayın. .replace(' ', '*')daha ziyade dolgu etkisini göstermeyi amaçlamıştır. Parola gizleme ifadesinde zaten bu sorun yok ... Yerel Java özelliğini kullanarak sol ve sağ dolgu dizesini özelleştirme konusunda daha iyi bir yanıt için diğer cevabımı görün.
leo

Dize yalnızca tek boşluklar içeriyorsa ve farklı karakterlerle doldurmak istiyorsanız, regex replace komutunu arkaya / ileriye bakarak kullanabilirsiniz: String.format("%30s", "pad left").replaceAll("(?<=( |^)) ", "*")veyaString.format("%-30s", "pad right").replaceAll(" (?=( |$))", "*")
Jaroslaw Pawlak


33

Basit bir şey:

Değer bir dize olmalıdır. değilse dizeye dönüştürün. Beğen "" + 123veyaInteger.toString(123)

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

Alt dize, değer uzunluğu karakter indeksinden dolgulu bitiş uzunluğuna kadar başlar:

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

// now padded is "00000123"

Daha kesin

ped sağ:

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

// now padded is "123DEFGH"

ped sol:

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

// now padded is "ABCDE123"

24

Bir bak org.apache.commons.lang.StringUtils#rightPad(String str, int size, char padChar).

Ancak algoritma çok basittir (boyut karakterlerine kadar ped):

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
Java 1.5'ten itibaren StringBuffer yerine StringBuilder kullanmaya değer olduğunu unutmayın.
Jon Skeet

21

Apache Commons'ın yanı sıra, String.formathangilerinin basit dolguya (örneğin boşluklarla) bakabilmesi gerektiğini de görün .


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
Dikkat: işlev adlarını ters çevirdiniz; Eğer koşarsan göreceksin.
mavimsi

artı orijinal str boşluk içeriyorsa, bu işe yaramaz
Steven Shaw

@StevenShaw Yanılmıyorsam, değiştirme orijinali hedeflemez str, bu yüzden bu doğrudur.
mafu

3
Kural olarak, işlev adları için büyük harf kullanmamalısınız.
temel-ideal-alan

Dizeyi ne zaman (length - str.length())olduğu gibi döndürmede eksik bir koşul var mı 0? Formatlayıcı , format dizesi bir FormatFlagsConversionMismatchExceptionzaman atar %0s.
Devin Walters

7

Anlamak biraz zaman aldı. Gerçek anahtar bu Formatter belgelerini okumaktır.

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

Sonu neden bu kadar karmaşık hale getirelim? Dize hex = String.format ("% 032x", özet); ve tam olarak aynı sonuçlara sahipti, sadece gereksiz bir değiştirme () olmadan ve belirli değişkenlere erişmek için $ kullanmak zorunda kaldım (sonuçta sadece bir tane var.)
ArtOfWarfare

@ArtOfWarfare adil bir nokta. Birisi aslında başka bir soruda onaltılık değerler doldurma istedi, ben biçimlendirici belgelerine bir bağlantı olduğunu gördüm. Tamlık için karmaşık.
Nthalk

6

i bu konu eski tür ve orijinal soru kolay bir çözüm olduğunu biliyorum ama gerçekten hızlı olması gerekiyorsa, bir char dizi kullanmalısınız.

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

formatlayıcı çözümü uygun değildir. sadece biçim dizesini oluşturmak 2 yeni dizge oluşturur.

apache'nin çözümü sb'yi hedef boyutla başlatarak geliştirilebilir, böylece aşağıda

StringBuffer padded = new StringBuffer(str); 

ile

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

SB'nin iç tamponunun büyümesini önleyecektir.


Eğer StringBuffer(bu durumda doğrudur) Aynı anda birden fazla iş parçacığı tarafından erişilemez, bir kullanmalıdır StringBuilder(JDK1.5 + olarak) senkronizasyon yükü önlemek için.
glen3b

5

Sağa doğru basmanın başka bir yolu:

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

Java 11'den bu yana, String.repeat (int) belirli bir dizeyi sol / sağ tuş takımı için kullanılabilir.

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

Çıktı:

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

1
Java 11 için en iyi cevap!
Nagy Attila

4

Her seferinde yeniden oluşturmak yerine doldurma verilerini koruyarak arama başına ek yükü azaltabilirsiniz:

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

}

Alternatif olarak, sonuç uzunluğunu pad(...)yönteme bir parametre yapabilirsiniz . Bu durumda, gizli dolgu ayarını yapıcı yerine bu yöntemde yapın.

(İpucu: Ekstra kredi için, iş parçacığı açısından güvenli yapın! ;-)


1
Güvenli olmayan yayınlar dışında bu iş parçacığı için güvenlidir (elbette alanlarınızı nihai yapın). Bence concat (garip bir şekilde) ile değiştirilmesi gereken + önce bir alt dize yaparak performans geliştirilebilir.
Tom Hawtin - taktik

3

Bunu Dzone'da buldum

Sıfırlı ped:

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

Bu basit ve özlü bir cevap olmalı, harici kütüphaneler kurmaya gerek yok.
Wong Jia Hau

2

değişken dize uzunluklarının doldurulması için yerleşik StringBuilder append () ve insert () yöntemlerini kullanabilirsiniz:

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

Örneğin:

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

Bu çalışıyor:

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

String XXX'nizi 9 karaktere kadar bir boşlukla dolduracaktır. Bundan sonra tüm Whitespaces 0 ile değiştirilecek. Beyaz alanı ve 0'ı istediğiniz gibi değiştirebilirsiniz ...


Sen çağırmak gerekir staticolarak yöntemini String.format(…)yerine boş bir dize kötüye. Kaynak kodda dört karakter kaydetmek kesinlikle okunabilirlik kaybına değmez.
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

Başka bir dizeye bitiştirmeden önce sol / sağ dolgu (veya önek / sonek dizesi veya boşlukları) vermeniz gereken bazı durumlar için bir cevap bırakalım ve uzunluğu veya herhangi bir if koşulunu test etmek istemiyorum.

Seçilen cevap için aynı StringUtils, Apache Commons tercih ederim ama bu şekilde kullanarak:

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

Açıklamak:

  • myString: Girdiğim dize boş olabilir
  • StringUtils.leftPad(myString, 1): dize null olursa, bu ifade de null değerini döndürür
  • sonra defaultStringnull değerini bitirmek için boş dize vermek için kullanın

2

@ck ve @Marlon Tarak'ın cevapları a'yı kullanmak için sadece cevaplardır, char[]bu da saniyede dolgu yöntemlerine birkaç çağrı yapan uygulamalar için en iyi yaklaşımdır. Ancak, herhangi bir dizi manipülasyon optimizasyonundan faydalanmazlar ve benim zevkime göre biraz üzerine yazılırlar; bu hiç bir döngü olmadan yapılabilir .

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

Basit test yöntemi:

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

Çıktılar:

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

1
Sen kullanabilirsiniz getCharsizin Stringdoğrudan içine içeriğini kopyalamak outyerine çağıran, dizinin source.toCharArray()izledi System.arraycopy. Uygulamayı basitleştirmeyi bile düşünürdüm 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);; Bu filldaha fazla iş yapar gibi görünüyor olsa da, aslında JVM'nin varsayılan sıfır dolumunu ortadan kaldırmasına izin verir.
Holger

1

java.util.Formattersol ve sağ dolgu yapacak. Garip üçüncü taraf bağımlılıklarına gerek yok (bunları önemsiz bir şey için eklemek ister misiniz).

[Ayrıntıları bıraktım ve ihtiyacım olan bir şey olmadığı için bu yayını 'topluluk wiki' yaptım.]


4
Katılmıyorum. Daha büyük bir Java projesinde genellikle çok fazla String manipülasyonu yapacaksınız, artan okunabilirlik ve hatalardan kaçınma Apache Commons Lang'ı kullanmaya değer. Hepiniz StringUtils ile kolayca önlenebilecek someString.subString (someString.indexOf (startCharacter), someString.lastIndexOf (endCharacter)) gibi kodu biliyorsunuzdur.
Bananeweizen

1

Tüm dize işlemlerinin genellikle çok verimli olması gerekir - özellikle büyük veri kümeleriyle çalışıyorsanız. Ben plsql pad komut alacak ne benzer, hızlı ve esnek bir şey istedim. Ayrıca, sadece küçük bir şey için büyük bir lib eklemek istemiyorum. Bu düşüncelerle bu çözümlerin hiçbiri tatmin edici değildi. Bu, benim geliştirdiğim, en iyi tezgah işaretleme sonuçlarına sahip olan çözümler, eğer herhangi biri üzerinde iyileştirebilirse, lütfen yorumunuzu ekleyin.

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;
    }
}
  • Not String.toCharArray () ile çağrılır ve sonuç yeni String ((char []) sonucu) ile String'e dönüştürülebilir. Bunun nedeni, birden fazla işlem uyguladığınızda hepsini char [] üzerinde yapabilir ve formatlar arasında dönüştürme yapmaya devam edemezsiniz - sahnelerin arkasında, String char [] olarak saklanır. Bu işlemler String sınıfının kendisine dahil edilmiş olsaydı, etkin hız ve bellek bakımından iki kat daha etkili olurdu.

Bu gerçekten en verimli yol gibi görünüyor
David Lilljegren

1

Bu işlevi kullanın.

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

nasıl kullanılır?

leftPadding(month, 2, '0');

çıktı: 01 02 03 04 .. 11 12


1

Bir çok insanın bazı çok ilginç teknikleri var ama bunu basit tutmayı seviyorum, bu yüzden bununla devam ediyorum:

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
Bu çok verimsiz, bir StringBuilder kullanmalısınız
wkarl

Uzunluğu zaten bildiğinizden, StringBuilder'a bunu başlatırken o kadar fazla alan ayırmasını söylemelisiniz.
Ariel

@Ariel ilginç çünkü bugün lol başka biriyle konuşuyordum çünkü.
Aelphaeis

0

Herhangi bir API'sı olmayan basit bir çözüm aşağıdaki gibi olacaktır:

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

Java oneliners, süslü kütüphane yok.

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

Pad Sol, sınırlama

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

Ped Sağ, sınırlama

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

Ped Sol, ped uzunluğu ile sınırlandır

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

Ped Sağ, ped uzunluğuyla sınırlandır

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

0

Özyineleme kullanmaya ne dersiniz? Aşağıda verilen çözüm tüm JDK sürümleriyle uyumludur ve harici kitaplığa gerek yoktur :)

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

NOT : Bu çözüm dolguyu ekleyecektir, küçük bir değişiklikle ped değerini önekleyebilirsiniz.


0

İşte çok uzun Dizeleri olanlar için paralel bir sürüm :-)

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

Basit bir çözüm:

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

-1

Bu nasıl

Dize "merhaba" ve gerekli dolgu "0" sol yastık ile 15

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

10
Bu, en fazla 15 yeni dize oluşturur.
claj

@claj Evet, ama bu .
16:23, ruffin
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.