



Apache StringUtils имеет несколько методов: leftPad, rightPad, center и repeat.
Но обратите внимание, что - как уже упоминалось и демонстрировалось в этот ответ - классы String.format() и Formatter в JDK являются лучшими вариантами. Используйте их поверх общего кода.
По нескольким причинам я бы предпочел Guava вместо Apache Commons; этот ответ показывает, как это сделать в Гуаве.
@Jonik, не могли бы вы перечислить некоторые из ваших причин? API выглядят почти так же.
@ glen3b: Для отдельной утилиты, такой как эти помощники по заполнению строк, действительно не имеет значения, какую библиотеку использовать. Тем не менее, Guava в целом является более современной, чистой и лучше документированной библиотекой, чем ее аналоги в различных проектах Apache Commons (Commons Lang, Commons Collections, Commons IO и т. д.). Он также построен действительно умными парнями (Кевин Бурриллион и др.), Многие из которых являются активен в SO. Я сам закончил замену различных библиотек Apache Commons всего лишь на Guava несколько лет назад и ни о чем не жалею.
@ glen3b: Хороший дальнейшее чтение по этому вопросу.
StringUtils / Strings по-прежнему является лучшим выбором IMO, когда размер площадки является переменной времени выполнения.
Помимо Apache Commons, также см. String.format, который должен иметь возможность позаботиться о простом заполнении (например, с пробелами).
Взгляните на org.apache.commons.lang.StringUtils#rightPad(String str, int size, char padChar).
Но алгоритм очень прост (заполните до символов размера):
public String pad(String str, int size, char padChar)
{
StringBuilder padded = new StringBuilder(str);
while (padded.length() < size)
{
padded.append(padChar);
}
return padded.toString();
}
Обратите внимание, что в Java 1.5 вместо StringBuffer стоит использовать StringBuilder.
Вы можете уменьшить накладные расходы на вызовы, сохранив данные заполнения, а не перестраивая их каждый раз:
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);
}
}
В качестве альтернативы вы можете сделать длину результата параметром метода pad(...). В этом случае настройте скрытые отступы в этом методе, а не в конструкторе.
(Подсказка: для дополнительного удобства сделайте его поточно-ориентированным! ;-)
Это потокобезопасно, за исключением небезопасной публикации (естественно, сделайте ваши поля окончательными). Я думаю, что производительность можно улучшить, добавив подстроку перед +, которую следует заменить на concat (как ни странно).
java.util.Formatter выполнит заполнение слева и справа. Нет необходимости в странных сторонних зависимостях (не хотите ли вы добавить их для чего-то столь тривиального).
[Я опустил детали и сделал этот пост «вики-сообществом», так как это не то, в чем я нуждаюсь.]
Я не согласен. В любом более крупном Java-проекте вы, как правило, будете выполнять столько манипуляций со строками, что для повышения удобочитаемости и предотвращения ошибок стоит использовать Apache Commons Lang. Все вы знаете такой код, как someString.subString (someString.indexOf (startCharacter), someString.lastIndexOf (endCharacter)), которого можно легко избежать с помощью StringUtils.
Начиная с Java 1.5, String.format() можно использовать для заполнения заданной строки влево / вправо.
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) + "*");
}
И результат:
Howto *
Howto*
Что делать, если вам нужно ввести lpad с другими символами (не пробелами)? Возможно ли это с помощью String.format? Я не могу заставить его работать ...
AFAIK String.format () не может этого сделать, но его не так сложно закодировать, см. rgagnon.com/javadetails/java-0448.html (2-й пример)
@ Nullw0rm, если вы имеете в виду rgagnon.com, имейте в виду, что RealHowTo также является автором rgagnon.com, поэтому он будет указывать на себя ...
по крайней мере, на моей JVM "#" не работает, "-" в порядке. (Просто удалите #). Это может быть согласовано с документацией по форматеру, я не знаю; он говорит: «'#' '\ u0023' Требует, чтобы в выводе использовалась альтернативная форма. Определение формы определяется преобразованием».
С jre6 "% 1 $ #" нормально, но с jre7 "% 1 $ #" выдает исключение java.util.FormatFlagsConversionMismatchException: Conversion = s, Flags = #. Я обновил этот ответ, удалив знак "#".
Спасибо за отличный ответ. Но я сомневаюсь, для чего нужен 1$? @leo дал очень похожий ответ, который не использует 1$, и, по-видимому, имеет тот же эффект. Есть ли разница?
О, конечно, это явно принудительный порядок аргументов String.format, извините за глупый вопрос. :P Я полагаю, что даже в этом случае он практически бесполезен.
Обратите внимание, что nдолжен больше, чем 0.
Начиная с Java 11, используйте String.repeat, см. Ниже ответ Эко Сетиавана.
Я получаю много странных результатов ... передайте это решение
вы можете использовать встроенные методы StringBuilder append () и insert (), для заполнения строк переменной длины:
AbstractStringBuilder append(CharSequence s, int start, int end) ;
Например:
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());
Я знаю, что этот поток довольно старый, и исходный вопрос был для простого решения, но если он должен быть очень быстрым, вы должны использовать массив символов.
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;
}
решение форматтера не оптимально. просто построение строки формата создает 2 новые строки.
Решение apache можно улучшить, инициализировав sb с целевым размером, заменив ниже
StringBuffer padded = new StringBuffer(str);
с участием
StringBuffer padded = new StringBuffer(pad);
padded.append(value);
предотвратит рост внутреннего буфера sb.
Если к StringBuffer не могут получить доступ сразу несколько потоков (что в данном случае верно), вы должны использовать StringBuilder (в JDK1.5 +), чтобы избежать накладных расходов на синхронизацию.
Мне потребовалось некоторое время, чтобы понять. Настоящий ключ - прочитать эту документацию 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);
Зачем так усложнять конец? Вы могли просто сделать String hex = String.format ("% 032x", дайджест); и имел точно такие же результаты, только без ненужной replace () и необходимости использовать $ для доступа к определенным переменным (в конце концов, есть только одна).
Выставка @ArtOfWarfare. Кто-то изначально просил заполнить шестнадцатеричные значения в другом вопросе, я увидел, что у меня есть ссылка на документацию по форматеру. Сложно для полноты.
Это работает:
"".format("%1$-" + 9 + "s", "XXX").replaceAll(" ", "0")
Он заполнит вашу строку XXX до 9 символов пробелом. После этого все пробелы будут заменены на 0. Вы можете изменить пробелы и 0 на все, что захотите ...
Вы должны вызывать метод static как String.format(…) вместо того, чтобы злоупотреблять пустой строкой. Сохранение четырех символов в исходном коде, безусловно, не стоит потери читабельности.
Заполнение до 10 символов:
String.format("%10s", "foo").replace(' ', '*');
String.format("%-10s", "bar").replace(' ', '*');
String.format("%10s", "longer than 10 chars").replace(' ', '*');
выход:
*******foo
bar*******
longer*than*10*chars
Отображайте '*' для символов пароля:
String password = "secret123";
String padded = String.format("%"+password.length()+"s", "").replace(' ', '*');
вывод имеет ту же длину, что и строка пароля:
secret123
*********
Пока мы все помним, что нельзя передавать строку с пробелами ...: D
Я использую @ aboveyou00 - это ужасное решение для строк с пробелами, включая пример, предоставленный leo. Решение для заполнения строки слева или справа не должно изменять входную строку в том виде, в котором она отображается на выходе, если исходное заполнение входной строки не приводит к превышению указанной длины заполнения.
Признайте проблему с космосом. .replace(' ', '*') был скорее предназначен для демонстрации эффекта заполнения. Выражение, скрывающее пароль, в любом случае не имеет этой проблемы ... Чтобы получить лучший ответ о настройке левой и правой строки заполнения с использованием встроенной функции Java, см. Мой другой ответ.
Если строка содержит только одиночные пробелы и вы хотите дополнить ее разными символами, вы можете использовать замену регулярного выражения с просмотром назад / вперед: String.format("%30s", "pad left").replaceAll("(?<=( |^)) ", "*") или String.format("%-30s", "pad right").replaceAll(" (?=( |$))", "*")
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 "";
}
Вот еще один способ сдвинуть вправо:
// 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-------";
В Гуава это просто:
Strings.padStart("string", 10, ' ');
Strings.padEnd("string", 10, ' ');
Простое решение:
package nl;
public class Padder {
public static void main(String[] args) {
String s = "123" ;
System.out.println("#"+(" " + s).substring(s.length())+"#");
}
}
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...
Обратите внимание: вы перевернули имена функций; если вы запустите его, вы увидите.
плюс, если исходная строка содержит пробелы, это не сработает
@StevenShaw Если я не ошибаюсь, замена не нацелена на оригинальный str, так что это правильно.
По соглашению вы не должны использовать заглавные буквы для имен функций.
Есть ли пропущенное условие для возврата строки, как если бы (length - str.length()) был 0? Средство форматирования выдает FormatFlagsConversionMismatchException, когда %0s является строкой формата.
Как это
Строка - "привет", а обязательное заполнение - 15, слева - "0".
String ax = "Hello";
while(ax.length() < 15) ax = "0"+ax;
этот генерирует до 15 новых строк.
@claj Да, но это.
Что-нибудь простое:
Значение должно быть строкой. преобразуйте его в строку, если это не так. Как "" + 123 или Integer.toString(123)
// let's assume value holds the String we want to pad
String value = "123";
Подстрока начинается с индекса длины значения char до конечной длины дополненной строки:
String padded = "00000000".substring(value.length()) + value;
// now padded is "00000123"
Точнее
площадка справа:
String padded = value + ("ABCDEFGH".substring(value.length()));
// now padded is "123DEFGH"
панель слева:
String padString = "ABCDEFGH";
String padded = (padString.substring(0, padString.length() - value.length())) + value;
// now padded is "ABCDE123"
У многих людей есть очень интересные техники, но я предпочитаю, чтобы они были простыми, поэтому я придерживаюсь следующего:
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();
}
Это очень неэффективно, вам следует использовать StringBuilder
Поскольку вы уже знаете длину, вы должны указать StringBuilder выделить столько места при его создании.
@Ariel интересно, что вы упомянули это, потому что я только что разговаривал с кем-то об этом сегодня, лол.
Позвольте мне оставить ответ для некоторых случаев, когда вам нужно указать левое / правое заполнение (или строку префикса / суффикса или пробелы) перед объединением с другой строкой, и вы не хотите проверять длину или какое-либо условие if.
Как и в выбранном ответе, я бы предпочел StringUtils Apache Commons, но используя этот способ:
StringUtils.defaultString(StringUtils.leftPad(myString, 1))
Объяснять:
myString: строка, которую я ввожу, может быть нулемStringUtils.leftPad(myString, 1): если строка равна нулю, этот оператор тоже вернет нульdefaultString, чтобы дать пустую строку, чтобы предотвратить конкатенацию nullПростое решение без API будет следующим:
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();
}
Ответы @ck и @ Марлон Тарак - единственные, которые используют char[], что для приложений, которые имеют несколько вызовов методов заполнения в секунду, является лучшим подходом. Однако они не используют преимущества каких-либо оптимизаций манипуляций с массивами и немного перезаписаны на мой вкус; это можно сделать с помощью без петель вообще.
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);
}
Простой метод проверки:
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));
}
Выходы:
012345678901234567890123456789
cats
cats
cats
cats$$$$$$$$$$$$$$$$$$$$$$$$$$
too long for your own good, buddy
Вы можете использовать getChars, чтобы позволить String копировать свое содержимое непосредственно в массив out, вместо вызова source.toCharArray(), за которым следует System.arraycopy. Я бы даже подумал об упрощении реализации до 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);; хотя похоже, что fill сделает больше работы, на самом деле он позволяет JVM исключить заполнение нулями по умолчанию.
Конструкторы Java, никакой навороченной библиотеки.
// 6 characters padding example
String pad = "******";
// testcases for 0, 4, 8 characters
String input = "" | "abcd" | "abcdefgh"
Pad Left, не ограничивайте
result = pad.substring(Math.min(input.length(),pad.length())) + input;
results: "******" | "**abcd" | "abcdefgh"
Pad Right, не ограничивайте
result = input + pad.substring(Math.min(input.length(),pad.length()));
results: "******" | "abcd**" | "abcdefgh"
Пэд слева, ограничение по длине пэда
result = (pad + input).substring(input.length(), input.length() + pad.length());
results: "******" | "**abcd" | "cdefgh"
Пэд вправо, ограничение по длине пэда
result = (input + pad).substring(0, pad.length());
results: "******" | "abcd**" | "abcdef"
Вся операция нить обычно должна быть очень эффективный - особенно если вы работаете с большими наборами данных. Я хотел что-то быстрое и гибкое, подобное тому, что вы получите в команде plsql pad. Кроме того, я не хочу включать огромную библиотеку только для одной мелочи. С учетом этих соображений ни одно из этих решений не было удовлетворительным. Это решения, которые я придумал, у которых были лучшие результаты тестирования, если кто-то может их улучшить, пожалуйста, добавьте свой комментарий.
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;
}
}
Это действительно выглядит как наиболее эффективный способ
Нашел это на Dzone
Pad с нулями:
String.format("|%020d|", 93); // prints: |00000000000000000093|
Это должен быть ответ, простой и лаконичный, без установки внешних библиотек.
Работает с числовыми значениями, но не со строковыми значениями: т. Е. Для «A83» это не сработает. 0 после процента вызовет исключение.
Воспользуйтесь этой функцией.
private String leftPadding(String word, int length, char ch) {
return (length > word.length()) ? leftPadding(ch + word, length, ch) : word;
}
как использовать?
leftPadding(month, 2, '0');
выход: 01 02 03 04 .. 11 12
Начиная с Java 11, String.repeat (int) можно использовать для заполнения заданной строки влево / вправо.
System.out.println("*".repeat(5)+"apple");
System.out.println("apple"+"*".repeat(5));
Выход:
*****apple
apple*****
Лучший ответ для Java 11!
Как насчет рекурсии? Приведенное ниже решение совместимо со всеми версиями JDK и не требует внешних библиотек :)
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);
}
}
ПРИМЕЧАНИЕ: это решение добавит отступ, с небольшой настройкой вы можете префикс значения поля.
Вот параллельная версия для тех из вас, у кого очень длинные строки :-)
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));
Этот служебный класс полезен для левая панель и нулевая заливка строк. Надеюсь, это кому-то поможет!
package your.package.name;
/**
* Utility class for left pad and zero fill of Strings.
*
*/
public class LeftPad {
public static String lpad(String string, int length, char fill) {
return new String(lpad(string.toCharArray(), length, fill));
}
public static String zerofill(String string, int length) {
return new String(zerofill(string.toCharArray(), length));
}
private static char[] lpad(char[] chars, int length, char fill) {
int delta = 0;
int limit = 0;
if (length > chars.length) {
delta = length - chars.length;
limit = length;
} else {
delta = 0;
limit = chars.length;
}
char[] output = new char[chars.length + delta];
for (int i = 0; i < limit; i++) {
if (i < delta) {
output[i] = fill;
} else {
output[i] = chars[i - delta];
}
}
return output;
}
private static char[] zerofill(char[] chars, int length) {
return lpad(chars, length, '0');
}
/**
* For tests!
*/
public static void main(String[] args) {
String string = "123";
char pad = ' ';
System.out.println("left pad blank: " + string);
System.out.println("Result: [" + LeftPad.lpad(string, 10, pad) + "]");
System.out.println();
System.out.println("zero fill: " + string);
System.out.println("Result: [" + LeftPad.zerofill(string, 10) + "]");
}
}
Это результат:
left pad blank: 123
Result: [ 123]
zero fill: 123
Result: [0000000123]
java.util.Formatter (и String.format ()) делает это. Всегда предпочитайте JDK внешней библиотеке, если версия JDK выполняет работу (что она делает).