Existe alguma maneira fácil de preencher Strings em Java?
Parece algo que deveria estar em alguma API do tipo StringUtil, mas não consigo encontrar nada que faça isso.
Existe alguma maneira fácil de preencher Strings em Java?
Parece algo que deveria estar em alguma API do tipo StringUtil, mas não consigo encontrar nada que faça isso.
Respostas:
Apache StringUtils
tem vários métodos: leftPad
, rightPad
, center
e repeat
.
Mas observe que - como outros já mencionaram e demonstraram nesta resposta - String.format()
e as Formatter
classes no JDK são melhores opções. Use-os sobre o código comum.
Desde o Java 1.5, String.format()
pode ser usado para preencher esquerda / direita uma determinada string.
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 a saída é:
Howto *
Howto*
1$
? @leo fez uma resposta muito semelhante que não usa 1$
e aparentemente tem o mesmo efeito. Isso faz diferença?
Preenchimento com 10 caracteres:
String.format("%10s", "foo").replace(' ', '*');
String.format("%-10s", "bar").replace(' ', '*');
String.format("%10s", "longer than 10 chars").replace(' ', '*');
resultado:
*******foo
bar*******
longer*than*10*chars
Exiba '*' para caracteres de senha:
String password = "secret123";
String padded = String.format("%"+password.length()+"s", "").replace(' ', '*');
A saída tem o mesmo comprimento que a string da senha:
secret123
*********
.replace(' ', '*')
teve a intenção de mostrar o efeito do preenchimento. A expressão oculta da senha não tem esse problema de qualquer maneira ... Para obter uma resposta melhor sobre como personalizar a cadeia de preenchimento esquerda e direita usando o recurso Java nativo, consulte minha outra resposta.
String.format("%30s", "pad left").replaceAll("(?<=( |^)) ", "*")
ouString.format("%-30s", "pad right").replaceAll(" (?=( |$))", "*")
Na Goiaba , isso é fácil:
Strings.padStart("string", 10, ' ');
Strings.padEnd("string", 10, ' ');
Algo simples:
O valor deve ser uma sequência. converta-o em string, se não estiver. Curtir "" + 123
ouInteger.toString(123)
// let's assume value holds the String we want to pad
String value = "123";
Início da cadeia de caracteres do índice de caracteres de comprimento do valor até o comprimento final do preenchimento:
String padded="00000000".substring(value.length()) + value;
// now padded is "00000123"
Mais preciso
almofada direita:
String padded = value + ("ABCDEFGH".substring(value.length()));
// now padded is "123DEFGH"
almofada esquerda:
String padString = "ABCDEFGH";
String padded = (padString.substring(0, padString.length() - value.length())) + value;
// now padded is "ABCDE123"
Dê uma olhada org.apache.commons.lang.StringUtils#rightPad(String str, int size, char padChar)
.
Mas o algoritmo é muito simples (pad até o tamanho dos caracteres):
public String pad(String str, int size, char padChar)
{
StringBuffer padded = new StringBuffer(str);
while (padded.length() < size)
{
padded.append(padChar);
}
return padded.toString();
}
Além do Apache Commons, veja também o String.format
que deve ser capaz de cuidar do preenchimento simples (por exemplo, com espaços).
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
, então isso está correto.
(length - str.length())
é 0
? O formatador lança a FormatFlagsConversionMismatchException
quando %0s
é a string de formato.
Demorei um pouco para descobrir. A chave real é ler a documentação do Formatador.
// 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);
Eu sei que este tópico é meio antigo e a pergunta original era para uma solução fácil, mas se deveria ser realmente rápido, você deve usar uma matriz de caracteres.
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;
}
a solução do formatador não é ótima. apenas construir a string de formato cria 2 novas strings.
A solução do apache pode ser aprimorada inicializando o sb com o tamanho do destino, substituindo-o abaixo
StringBuffer padded = new StringBuffer(str);
com
StringBuffer padded = new StringBuffer(pad);
padded.append(value);
impediria o crescimento do buffer interno do sb.
StringBuffer
não puder ser acessado por vários encadeamentos de uma só vez (o que neste caso é verdadeiro), você deverá usar um StringBuilder
(no JDK1.5 +) para evitar a sobrecarga da sincronização.
Aqui está outra maneira de colocar à direita:
// 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-------";
Desde o Java 11, String.repeat (int) pode ser usado para preencher esquerda / direita uma determinada string.
System.out.println("*".repeat(5)+"apple");
System.out.println("apple"+"*".repeat(5));
Resultado:
*****apple
apple*****
Você pode reduzir a sobrecarga por chamada mantendo os dados de preenchimento, em vez de recriá-los sempre:
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);
}
}
Como alternativa, você pode tornar o comprimento do resultado um parâmetro para o pad(...)
método Nesse caso, faça o ajuste do preenchimento oculto nesse método em vez de no construtor.
(Dica: para obter crédito extra, torne-o seguro para threads! ;-)
Encontrei isso no Dzone
Almofada com zeros:
String.format("|%020d|", 93); // prints: |00000000000000000093|
você pode usar os métodos incorporados StringBuilder append () e insert (), para preenchimento de comprimentos variáveis de string:
AbstractStringBuilder append(CharSequence s, int start, int end) ;
Por exemplo:
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());
Isso funciona:
"".format("%1$-" + 9 + "s", "XXX").replaceAll(" ", "0")
Ele preencherá sua String XXX até 9 caracteres com um espaço em branco. Depois disso, todos os espaços em branco serão substituídos por um 0. Você pode alterar o espaço em branco e o 0 para o que quiser ...
static
método para String.format(…)
não abusar de uma sequência vazia. Salvar quatro caracteres no código fonte certamente não vale a perda de legibilidade.
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 "";
}
Deixe-me deixar uma resposta para alguns casos em que você precisa fornecer preenchimento esquerdo / direito (ou sequência ou espaços de prefixo / sufixo) antes de concatenar para outra sequência e não desejar testar o comprimento ou qualquer condição if.
O mesmo que a resposta selecionada, eu preferiria o StringUtils
Apache Commons, mas usando desta maneira:
StringUtils.defaultString(StringUtils.leftPad(myString, 1))
Explicar:
myString
: a string que eu insiro, pode ser nulaStringUtils.leftPad(myString, 1)
: se a cadeia for nula, esta instrução retornará nulo tambémdefaultString
para dar uma string vazia para evitar concatenar nullAs respostas @ck e @Marlon Tarak são as únicas a usar a char[]
, o que para aplicativos que têm várias chamadas para métodos de preenchimento por segundo é a melhor abordagem. No entanto, eles não tiram vantagem de nenhuma otimização de manipulação de array e são um pouco substituídos pelo meu gosto; isso pode ser feito sem loops .
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étodo de teste simples:
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));
}
Saídas:
012345678901234567890123456789
cats
cats
cats
cats$$$$$$$$$$$$$$$$$$$$$$$$$$
too long for your own good, buddy
getChars
para permitir que o String
conteúdo seja copiado diretamente na out
matriz, em vez de chamar source.toCharArray()
, seguido por System.arraycopy
. Eu consideraria até simplificar a implementação 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);
; embora isso pareça fill
mais trabalhoso, na verdade permite que a JVM elimine o preenchimento zero padrão.
java.util.Formatter
fará preenchimento esquerdo e direito. Não há necessidade de dependências estranhas de terceiros (você gostaria de adicioná-las para algo tão trivial).
[Deixei de fora os detalhes e criei este post como 'wiki da comunidade', pois não é algo que eu precise.]
Toda operação de cadeia geralmente precisa ser muito eficiente - especialmente se você estiver trabalhando com grandes conjuntos de dados. Eu queria algo rápido e flexível, semelhante ao que você obterá no comando plsql pad. Além disso, não quero incluir uma enorme lib por apenas uma pequena coisa. Com essas considerações, nenhuma dessas soluções foi satisfatória. Estas são as soluções que eu encontrei, que tiveram os melhores resultados de benchmarking, se alguém puder melhorar, adicione seu comentário.
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;
}
}
Use esta função.
private String leftPadding(String word, int length, char ch) {
return (length > word.length()) ? leftPadding(ch + word, length, ch) : word;
}
Como usar?
leftPadding(month, 2, '0');
saída: 01 02 03 04 .. 11 12
Muitas pessoas têm algumas técnicas muito interessantes, mas eu gosto de simplificar, então eu vou com isso:
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();
}
Uma solução simples sem qualquer API será a seguinte:
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 de Java, nenhuma biblioteca sofisticada.
// 6 characters padding example
String pad = "******";
// testcases for 0, 4, 8 characters
String input = "" | "abcd" | "abcdefgh"
Almofada à esquerda, não limite
result = pad.substring(Math.min(input.length(),pad.length())) + input;
results: "******" | "**abcd" | "abcdefgh"
Almofada direita, não limite
result = input + pad.substring(Math.min(input.length(),pad.length()));
results: "******" | "abcd**" | "abcdefgh"
Almofada esquerda, limite do comprimento da almofada
result = (pad + input).substring(input.length(), input.length() + pad.length());
results: "******" | "**abcd" | "cdefgh"
Almofada direita, limite ao comprimento da almofada
result = (input + pad).substring(0, pad.length());
results: "******" | "abcd**" | "abcdef"
Que tal usar recursão? A solução fornecida abaixo é compatível com todas as versões do JDK e sem a necessidade de bibliotecas externas :)
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 : Esta solução acrescentará o preenchimento. Com um pequeno ajuste, você pode prefixar o valor do preenchimento.
Aqui está uma versão paralela para aqueles que têm seqüências muito longas :-)
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));
Exemplos de preenchimento na goiaba:
Exemplos de preenchimento no Apache Commons:
Exemplos de preenchimento no JDK:
Uma solução simples seria:
package nl;
public class Padder {
public static void main(String[] args) {
String s = "123" ;
System.out.println("#"+(" " + s).substring(s.length())+"#");
}
}