如何在Java中填充字符串?

505

有没有一种简单的方法在Java中填充字符串?

这似乎是一些类似于StringUtil的API应该有的东西,但我找不到任何可以实现这一点的内容。

33个回答

730

自从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*

48
如果您需要使用其他字符(而不是空格)进行填充,该怎么办?使用String.format仍然可能吗?我无法使其起作用... - Guido
6
据我所知,String.format()无法完成此操作,但编写这样的代码并不太困难,请参见http://www.rgagnon.com/javadetails/java-0448.html(第二个示例)。 - RealHowTo
62
如果你指的是rgagnon.com,那么请注意RealHowTo也是rgagnon.com的作者,所以他会将功劳归于自己... - Colin Pickard
3
在我的 JVM 上,"#" 不起作用,但"-"可以。只需删除 "#" 即可。(可能与格式化程序文档一致,我不确定。文档中说:“'#' '\u0023' 要求输出使用备用形式。该形式的定义由转换指定。”) - gatoatigrado
7
谢谢您提供出色的答案。我有一个疑问,1$是什么意思?@leo给出了一个非常相似的答案,但没有使用1$,它似乎具有相同的效果。这会有所区别吗? - Fabrício Matté
显示剩余4条评论

293

填充到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
  *********

59
只要我们都记得不要传递带有空格的字符串就好了... :D - leviathanbadger
5
我同意@aboveyou00的观点——对于包含空格的字符串,包括leo提供的示例,这是一个可怕的解决方案。左侧或右侧填充字符串的解决方案不应更改输出中输入字符串的外观,除非输入字符串的原始填充使其超过指定的填充长度。 - Brian Warshaw
3
认识到空格问题。.replace(' ', '*') 的目的是展示填充效果,密码隐藏表达式本身没有这个问题...如果想要更好地定制左右填充字符串,请参考我的另一个答案,使用Java原生特性。 - leo
如果字符串仅包含单个空格并且您想要使用不同的字符进行填充,则可以使用正则表达式替换与前后查找:String.format("%30s", "pad left").replaceAll("(?<=( |^)) ", "*")String.format("%-30s", "pad right").replaceAll(" (?=( |$))", "*") - Jaroslaw Pawlak

208

Apache StringUtils 提供了多个方法: leftPad, rightPad, centerrepeat

但请注意,正如其他人在这个答案中所提到并证明的那样,JDK 中的 String.format()Formatter 类是更好的选项。与 commons 代码相比,请使用它们。


104
java.util.Formatter(以及String.format())可以实现这一点。如果JDK版本能够胜任任务(事实上可以),则始终优先选择JDK而不是外部库。 - cletus
6
因为几个原因,我现在更喜欢使用Guava而不是Apache Commons;这个答案展示了如何在Guava中实现 - Jonik
1
@Jonik,你介意列出一些你的理由吗?这些API看起来基本相同。 - glen3b
3
对于像这些字符串填充助手这样的个人实用程序来说,使用哪个库并没有太大区别。话虽如此,Guava总体上比各种Apache Commons项目(Commons Lang、Commons Collections、Commons IO等)中的竞争对手更现代化、更干净、文档更好。它也是由非常聪明的人(Kevin Bourrillion等)构建的,其中许多人在SO上活跃。我自己数年前就用Guava代替了各种Apache Commons库,一直没有后悔过。 - Jonik
3
@glen3b:这个问题有一些很好的进一步阅读材料 - Jonik
2
在我看来,当填充大小是运行时变量时,StringUtils/Strings 仍然是更好的选择。 - OrangeDog

87

Guava 中,这很容易:

Strings.padStart("string", 10, ' ');
Strings.padEnd("string", 10, ' ');

2
为了一个已经包含在标准JDK中的填充,就要添加2.7MB的代码依赖?说真的。 - foo
看了一下Guava源代码中这些方法的实现,这种愚蠢的短路设计几乎让它们无法使用:if (string.length() >= minLength) { return string; } :( - Dut A.

42

简单内容:

该值应为字符串。如果不是,请将其转换为字符串。例如,使用 "" + 123Integer.toString(123)

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

从值长度处开始的子字符串,直到填充后的末尾长度:

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"

29

请看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();
}

12
注意,从Java 1.5开始,建议使用StringBuilder而不是StringBuffer。 - Jon Skeet

22
除了使用Apache Commons之外,还可以查看String.format函数,它可以简单地实现填充(例如使用空格)。

19

自Java 11以来,可以使用String.repeat(int)来填充给定字符串的左侧/右侧。

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

输出:

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

2
对于填充来说,数字取决于字符串长度。如果不需要填充(负数),会发生什么? - Boaz
@Boaz 我泛化了它,这样如果输入字符串比所需的填充大小要大,就什么也不会发生。 - ggorlen

16
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
注意:你颠倒了函数名称;如果你运行它,就会发现。 - bluish
如果原始字符串包含空格,则此方法无法正常工作。 - Steven Shaw
如果我没记错的话,replace不会针对原始的str进行操作,所以这是正确的。 - mafu
3
按照惯例,函数名不应该使用大写字母。 - principal-ideal-domain
(length - str.length())0 时,返回字符串本身的条件是否缺失?当格式化字符串为 %0s 时,格式化程序会引发 FormatFlagsConversionMismatchException 异常。 - Devin Walters

9

在以下Dzone网站找到:

使用零进行填充:

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

1
这应该是答案,简单明了,无需安装外部库。 - Wong Jia Hau
仅适用于数字值,不适用于字符串值:例如,对于“A83”,它将无法工作。百分号后面的0会引发异常。 - TwiXter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接