How to format a string to add spaces to the right in a printed table?

Asked

Viewed 73 times

5

I am trying to print a table in Java using the method System.out.format, where the exit should be this way:

(Dados apenas de exemplo. Não são reais.)

SBGR -> BCO   | 9,0 m     | 5,0 NM   | 1400 Ft/m | 700
BCO  -> GHK   | 15,5 m    | 67,0 NM  | 2000 Ft/m | 2130
GHK  -> NIBIL | 11,7 m    | 125,0 NM | 700 Ft/m  | 3700

The code I’m using at the moment is this:

String format = "%s -> %6s | %4.1f m | %5.1f NM | %6d Ft/m | %6d\n";
System.out.format(format, origin, destination, estimatedTime, distance, verticalSpeed, estimatedFuel);

I know that the current code, for what I am looking for, is wrong because the number of spaces is to the left of the point, in the format string. However, if I put the number of spaces to the right of the point, I would have numbers instead of blank spaces.

My question is: what format to add whitespace to the right of the value, be it a string or a number?

1 answer

6


In the documentation of format there is a link to the page "Format String Syntax", that describes all possible options. There we find this table:

Flag General Character Integral Floating Point Date/Time Description
'-' y y y y y The result will be left-Justified
'#' y - y y - The result should use a Conversion-dependent Alternate form
'+' - - y y - The result will Always include a Sign
' ' - - y y - The result will include a Leading space for Positive values
'0' - - y y - The result will be zero-Padded
',' - - y y - The result will include locale-specific grouping separators
'(' - - y y - The result will enclose Negative Numbers in parentheses

That is, to align to the left, just use the hyphen in the format: %-4.1f instead of %4.1f, for example. The problem is that it only formats the number, but you want to format also the measure drive together, then only that wouldn’t work:

String origin = "SGBR", destination = "BCO";
double estimatedTime = 9, distance = 5;
int verticalSpeed = 1400, estimatedFuel = 700;
String format = "%s -> %6s | %-4.1f m | %-5.1f NM | %-6d Ft/m | %-6d\n";
System.out.format(format, origin, destination, estimatedTime, distance, verticalSpeed, estimatedFuel);

The exit would be:

SGBR ->    BCO | 9.0  m | 5.0   NM | 1400   Ft/m | 700   

Notice that only the numbers were aligned to the left, so it was 5.0 NM instead of 5.0 NM and more spaces after it (note also that the decimal separator varies according to the default locale of the JVM, but we’ll get there).


Anyway, in your case, you do not want to format only the number, but the number followed by the unit of measure, and already formatted with the comma separating the decimal places. That is, you want to format a left-aligned string (this string is formed by a number plus the unit of measure).

So I suggest first formatting the numbers along with the measure drive, generating the respective strings, and then formatting these strings by aligning left.

Something like that:

// junta o número com a unidade de medida
// o locale é para controlar o separador decimal
static String formataNumero(double valor, String unidade, int casasDecimais, Locale locale) {
    if (unidade.isEmpty()) { // sem unidade, formata só o número
        return String.format(locale, "%." + casasDecimais + "f", valor);
    }
    // com unidade, junta com o número
    return String.format(locale, "%." + casasDecimais + "f %s", valor, unidade);
}

public static void main(String[] args) {
    String origin = "SGBR", destination = "BCO";
    double estimatedTime = 9, distance = 5;
    int verticalSpeed = 1400, estimatedFuel = 700;
    Locale locale = new Locale("pt", "BR"); // para usar a vírgula como separador decimal

    String format = "%-4s -> %-6s| %-9s | %-8s | %-9s | %s\n";
    System.out.format(format, origin, destination,
            formataNumero(estimatedTime, "m", 1, locale),
            formataNumero(distance, "NM", 1, locale),
            formataNumero(verticalSpeed, "Ft/m", 0, locale), // inteiros usam zero casas decimais
            formataNumero(estimatedFuel, "", 0, locale));
}

I used a Locale for the decimal separator to be the comma (I used "en-BR", which is equivalent to Brazilian Portuguese). If you do not specify one, it will use the default locale which is configured in the JVM, and may not always be what you need (for example, if it is English, the separator will be the point). In addition, the default locale may be amended in Runtime by any application running on the same JVM, and you don’t have much control over it. So it’s best to use a locale specific.

So, I just need to format strings. I adjusted the sizes to match your desired output:

SGBR -> BCO   | 9,0 m     | 5,0 NM   | 1400 Ft/m | 700

But then you can adjust to whatever you need. Note that the last number does not need to be aligned to the left, as there is nothing after it. If you used something like %-6s, there would be some blanks at the end, but since it’s the last line information, I didn’t think it was necessary.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.