25
public class Divers {
  public static void main(String args[]){

     String format = "|%1$-10s|%2$-10s|%3$-20s|\n";
     System.out.format(format, "FirstName", "Init.", "LastName");
     System.out.format(format, "Real", "", "Gagnon");
     System.out.format(format, "John", "D", "Doe");

     String ex[] = { "John", "F.", "Kennedy" };

     System.out.format(String.format(format, (Object[])ex));
  }
}

output:

|FirstName |Init.     |LastName            |
|Real      |          |Gagnon              |
|John      |D         |Doe                 |
|John      |F.        |Kennedy             |

I want the output to be centered. If I do not use '-' flag the output will be aligned to the right.

I did not find a flag to center text in the API.

This article has some information about format, but nothing on centre justify.

razlebe
  • 7,134
  • 6
  • 42
  • 57
rana
  • 558
  • 2
  • 9
  • 32
  • The output is actually a table, so some reason question does not show the table properly. – rana Nov 16 '11 at 15:44
  • 3
    See `StringUtils` [http://stackoverflow.com/questions/2709993/how-to-center-string-output-using-printf-and-variable-width-java](http://stackoverflow.com/questions/2709993/how-to-center-string-output-using-printf-and-variable-width-java) **or** [http://www.java2s.com/Code/Java/Data-Type/CentersaStringinalargerStringofsizesizeusingthespacecharacter.htm](http://www.java2s.com/Code/Java/Data-Type/CentersaStringinalargerStringofsizesizeusingthespacecharacter.htm) – ecle Nov 16 '11 at 15:46
  • @eee is StringUtils in the standard library? – rana Nov 16 '11 at 15:54
  • 1
    `StringUtils` library comes from Apache (Apache license) [http://commons.apache.org/lang/](http://commons.apache.org/lang/) – ecle Nov 16 '11 at 15:55
  • 1
    @eee thanks a lot. Is there a way to do this using the standard library? – rana Nov 16 '11 at 16:02
  • If you look through the second link, you can use the standard library :) – ecle Nov 16 '11 at 16:04

9 Answers9

26

I quickly hacked this up. You can now use StringUtils.center(String s, int size) in String.format.

import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class TestCenter {
    @Test
    public void centersString() {
        assertThat(StringUtils.center(null, 0), equalTo(null));
        assertThat(StringUtils.center("foo", 3), is("foo"));
        assertThat(StringUtils.center("foo", -1), is("foo"));
        assertThat(StringUtils.center("moon", 10), is("   moon   "));
        assertThat(StringUtils.center("phone", 14, '*'), is("****phone*****"));
        assertThat(StringUtils.center("India", 6, '-'), is("India-"));
        assertThat(StringUtils.center("Eclipse IDE", 21, '*'), is("*****Eclipse IDE*****"));
    }

    @Test
    public void worksWithFormat() {
        String format = "|%1$-10s|%2$-10s|%3$-20s|\n";
        assertThat(String.format(format, StringUtils.center("FirstName", 10), StringUtils.center("Init.", 10), StringUtils.center("LastName", 20)),
                is("|FirstName |  Init.   |      LastName      |\n"));
    }
}

class StringUtils {

    public static String center(String s, int size) {
        return center(s, size, ' ');
    }

    public static String center(String s, int size, char pad) {
        if (s == null || size <= s.length())
            return s;

        StringBuilder sb = new StringBuilder(size);
        for (int i = 0; i < (size - s.length()) / 2; i++) {
            sb.append(pad);
        }
        sb.append(s);
        while (sb.length() < size) {
            sb.append(pad);
        }
        return sb.toString();
    }
}
Oliv
  • 10,221
  • 3
  • 55
  • 76
Sahil Muthoo
  • 12,033
  • 2
  • 29
  • 38
  • 1
    I will stick to StringUtils from apache commons lang since it is easy to integrate that using maven – rana Nov 16 '11 at 17:31
  • The `pad` argument is `String`, but if it is longer than 1 character, the method will not work correctly. This test will fail `assertEquals("01foo01", StringUtils.center("foo", 6, "0123"));`. It should be char. I'll fix that. – Oliv Aug 03 '16 at 08:56
18
public static String center(String text, int len){
    String out = String.format("%"+len+"s%s%"+len+"s", "",text,"");
    float mid = (out.length()/2);
    float start = mid - (len/2);
    float end = start + len; 
    return out.substring((int)start, (int)end);
}

public static void main(String[] args) throws Exception{
    // Test
    String s = "abcdefghijklmnopqrstuvwxyz";
    for (int i = 1; i < 200;i++){
        for (int j = 1; j < s.length();j++){
            //center(s.substring(0, j),i);
            System.out.println(center(s.substring(0, j),i));
        }
    }
}
Mertuarez
  • 901
  • 7
  • 24
  • 4
    Great answer! Might want to consider making your method names lowercase, the capitalization makes it seem like it is a class rather then a method. – papezjustin Jul 31 '13 at 17:01
15

Converted the code found at https://www.leveluplunch.com/java/examples/center-justify-string/ into a handy, small one-line function:

public static String centerString (int width, String s) {
    return String.format("%-" + width  + "s", String.format("%" + (s.length() + (width - s.length()) / 2) + "s", s));
}

Usage:

public static void main(String[] args){
    String out = centerString(10, "afgb");
    System.out.println(out); //Prints "   afgb   "
}

I think it's a very neat solution that's worth mentioning.

rapgru
  • 368
  • 2
  • 9
9

Here's the answer using apache commons lang StringUtils.

Please note that you have to add the jar file to the build path. If you are using maven make sure to add commons lang in the dependencies.

import org.apache.commons.lang.StringUtils;
public class Divers {
  public static void main(String args[]){

    String format = "|%1$-10s|%2$-10s|%3$-20s|\n";
    System.out.format(format, "FirstName", "Init.", "LastName");
    System.out.format(format,StringUtils.center("Real",10),StringUtils.center("",10),StringUtils.center("Gagnon",20);

    System.out.format(String.format(format, (Object[])ex));
  }
}
rana
  • 558
  • 2
  • 9
  • 32
6
int spaceSize = n - s.length();
int prefixSize = spaceSize / 2;
int suffixSize = (spaceSize + 1) / 2

"one-liner" since Java 11

return n > s.length()
     ? " ".repeat(prefixSize) + s + " ".repeat(suffixSize)
     : s;

Inlining the above vars into one return we can get:

return n > s.length() ? " ".repeat((n - s.length()) / 2) + s + " ".repeat((n - s.length() + 1) / 2**)** : s;


since Java 8

Java 8 has no " ".repeat(10) method. So

  • just replace the " ".repeat(10) with Java 8 analog. See https://stackoverflow.com/a/57514604/601844, and

  • use the same (as Java 11 ☝️) alg:

      int spaceSize = n - s.length();
      int prefixSize = spaceSize / 2;
      int suffixSize = (spaceSize + 1) / 2
      return n > s.length()
           ? space(prefixSize) + s + space(suffixSize)
           : s;
    
    
    private String space(int spaceSize) {
      return generate(() -> " ").limit(spaceSize).collect(joining());
    }
    
epox
  • 9,236
  • 1
  • 55
  • 38
3

I was playing around with Mertuarez's elegant answer above and decided to post my version.

public class CenterString {

    public static String center(String text, int len){
        if (len <= text.length())
            return text.substring(0, len);
        int before = (len - text.length())/2;
        if (before == 0)
            return String.format("%-" + len + "s", text);
        int rest = len - before;
        return String.format("%" + before + "s%-" + rest + "s", "", text);  
    }

    // Test
    public static void main(String[] args) {
        String s = "abcde";
        for (int i = 1; i < 10; i++){
            int max = Math.min(i,  s.length());
            for (int j = 1; j <= max; j++){
                System.out.println(center(s.substring(0, j), i) + "|");
            }
        }
    }
}

Output:

a|
a |
ab|
 a |
ab |
abc|
 a  |
 ab |
abc |
abcd|
  a  |
 ab  |
 abc |
abcd |
abcde|
  a   |
  ab  |
 abc  |
 abcd |
abcde |
   a   |
  ab   |
  abc  |
 abcd  |
 abcde |
   a    |
   ab   |
  abc   |
  abcd  |
 abcde  |
    a    |
   ab    |
   abc   |
  abcd   |
  abcde  | 

Practical differences from Mertuarez's code:

  1. Mine does the math up-front and makes the final centered string in one shot instead of making a too-long string and then taking a substring from it. I assume this is slightly more performant, but I did not test it.
  2. In the case of text that can't be perfectly centered, mine consistently puts it half a character to the left rather than putting it half a character to the right half of the time.
  3. In the case of text that's longer than the specified length, mine consistently returns a substring of the specified length that's rooted at the beginning of the original text.
MarredCheese
  • 17,541
  • 8
  • 92
  • 91
2

This is another way to place a string in center.

public static void center(String s, int length, CharSequence ch) {
    /* It works as follows
     * String centerString = String.format("|%" + (length - s.length()) + "s", s);
     * centerString = String.format("%" + -length + "s|", centerString);
     * System.out.println(centerString);
     */

    String centerString = String.format("%-" + length + "s|", String.format("|%" + (length - s.length()) + "s", s));
    System.out.println(centerString);
}
1

Here's an example of how I've handled centering column headers in Java:

public class Test {
    public static void main(String[] args) {
        String[] months = { "January", "February", "March", "April", "May", "June", "July", "August", "September",
                "October", "November", "December" };

        // Find length of longest months value.
        int maxLengthMonth = 0;
        boolean firstValue = true;
        for (String month : months) {
            maxLengthMonth = (firstValue) ? month.length() : Math.max(maxLengthMonth, month.length());
            firstValue = false;
        }

        // Display months in column header row
        for (String month : months) {
            StringBuilder columnHeader = new StringBuilder(month);
            // Add space to front or back of columnHeader
            boolean addAtEnd = true;
            while (columnHeader.length() < maxLengthMonth) {
                if (addAtEnd) {
                    columnHeader.append(" ");
                    addAtEnd = false;
                } else {
                    columnHeader.insert(0, " ");
                    addAtEnd = true;
                }
            }
            // Display column header with two extra leading spaces for each
            // column
            String format = "  %" + Integer.toString(maxLengthMonth) + "s";
            System.out.printf(format, columnHeader);
        }
        System.out.println();

        // Display 10 rows of random numbers
        for (int i = 0; i < 10; i++) {
            for (String month : months) {
                double randomValue = Math.random() * 999999;
                String format = "  %" + Integer.toString(maxLengthMonth) + ".2f";
                System.out.printf(format, randomValue);
            }
            System.out.println();
        }
    }
}
Rick Upton
  • 31
  • 2
1

Here's another example. Allows you to choose how you want to treat the center when there is a different number of padding characters added to the beginning and end of the string.

Uses Java 11 String::repeat.

public class Strings {

    public enum Lean {
        START,
        END
    }

    public static String center(String value, int targetLength, Lean lean) {
        return center(value, targetLength, lean, ' ');
    }

    private static String center(String value, int targetLength, Lean lean, char pad) {

        if (targetLength < 1) {
            throw new IllegalArgumentException("Cannot center something into less than one space.");
        }

        int sourceLength = value.length();

        if (sourceLength == targetLength) {
            return value;
        }

        int paddingToAdd = targetLength - sourceLength;
        int half = paddingToAdd / 2;
        String spad = Character.toString(pad);
        String padding = spad.repeat(half);
        String startExtra = "";
        String endExtra = "";

        if (paddingToAdd % 2 == 1) {
            if (lean == Lean.START) {
                endExtra = spad;
            } else {
                startExtra = spad;
            }
        }

        return padding + startExtra + value + endExtra + padding;
    }
}



public class StringsTest {

    @Test
    public void centerAbcIn9LeanStart() {
        doTest(
                "abc",
                9,
                Strings.Lean.START,
                "   abc   "
        );
    }

    @Test
    public void centerAbcIn9LeanEnd() {
        doTest(
                "abc",
                9,
                Strings.Lean.END,
                "   abc   "
        );
    }

    @Test
    public void centerAbcIn10LeanStart() {
        doTest(
                "abc",
                10,
                Strings.Lean.START,
                "   abc    "
        );
    }

    @Test
    public void centerAbcIn10LeanEnd() {
        doTest(
                "abc",
                10,
                Strings.Lean.END,
                "    abc   "
        );
    }

    @Test
    public void centerAbcdIn9LeanStart() {
        doTest(
                "abcd",
                9,
                Strings.Lean.START,
                "  abcd   "
        );
    }

    @Test
    public void centerAbcdIn9LeanEnd() {
        doTest(
                "abcd",
                9,
                Strings.Lean.END,
                "   abcd  "
        );
    }

    @Test
    public void centerAbcdIn10LeanStart() {
        doTest(
                "abcd",
                10,
                Strings.Lean.START,
                "   abcd   "
        );
    }

    @Test
    public void centerAbcdIn10LeanEnd() {
        doTest(
                "abcd",
                10,
                Strings.Lean.START,
                "   abcd   "
        );
    }

    @Test
    public void centerAIn1LeanStart() {
        doTest(
                "a",
                1,
                Strings.Lean.START,
                "a"
        );
    }

    @Test
    public void centerAIn1LeanEnd() {
        doTest(
                "a",
                1,
                Strings.Lean.END,
                "a"
        );
    }

    @Test
    public void centerAIn2LeanStart() {
        doTest(
                "a",
                2,
                Strings.Lean.START,
                "a "
        );
    }

    @Test
    public void centerAIn2LeanEnd() {
        doTest(
                "a",
                2,
                Strings.Lean.END,
                " a"
        );
    }

    @Test
    public void centerAIn3LeanStart() {
        doTest(
                "a",
                3,
                Strings.Lean.START,
                " a "
        );
    }

    @Test
    public void centerAIn3LeanEnd() {
        doTest(
                "a",
                3,
                Strings.Lean.END,
                " a "
        );
    }

    @Test
    public void centerAbIn3LeanStart() {
        doTest(
                "ab",
                3,
                Strings.Lean.START,
                "ab "
        );
    }

    @Test
    public void centerAbIn3LeanEnd() {
        doTest(
                "ab",
                3,
                Strings.Lean.END,
                " ab"
        );
    }

    public void doTest(String value, int targetLength, Strings.Lean lean, String expected) {

        assertThat(
                "Test setup error: targetLength != expected.length()",
                targetLength,
                equalTo(expected.length()));

        assertThat(
                "Test setup error: value != expected.trim()",
                value,
                equalTo(expected.trim()));

        String actual = Strings.center(value, targetLength, lean);
        assertThat(actual, equalTo(expected));
    }
}
Samuel Neff
  • 73,278
  • 17
  • 138
  • 182