Ausgabe in einem Tabellenformat in Javas System.out

89

Ich erhalte Ergebnisse aus einer Datenbank und möchte die Daten als Tabelle in Javas Standardausgabe ausgeben

Ich habe versucht, \ t zu verwenden, aber die erste Spalte, die ich möchte, ist sehr unterschiedlich lang.

Gibt es eine Möglichkeit, dies in einer schönen Tabelle wie der Ausgabe anzuzeigen?

Chris
quelle

Antworten:

144

Verwenden Sie System.out.format. Sie können die Länge von Feldern wie folgt festlegen:

System.out.format("%32s%10d%16s", string1, int1, string2);

Diese Pads string1, int1und string2auf 32, 10 und 16 Zeichen auf.

java.util.FormatterWeitere Informationen zur Syntax finden Sie in den Javadocs ( System.out.formatverwendet Formatterintern eine).

Michael Myers
quelle
1
Danke genau das, was ich brauchte! Ich füge nur hinzu, dass ich \ n am Ende setzen muss, um jedes Mal eine neue Zeile zu erstellen, falls jemand anderes dieses Problem findet.
Chris
19
Oder besser a %n- es wird automatisch in den Standard-Zeilenabschluss des Systems übersetzt.
Michael Myers
1
Wie kann ich die linke Ausrichtung in der Zeichenfolgentabelle vornehmen?
Mike
15
Links ausrichten: System.out.format ("% - 2s% 10d% -16s", string1, int1, string2);
Mike
1
Wie mache ich es, wenn ich es zentrieren möchte?
Pratnala
36

Mit j-text-utils können Sie drucken, um eine Tabelle wie folgt zu trösten: Geben Sie hier die Bildbeschreibung ein

Und es ist so einfach wie:

TextTable tt = new TextTable(columnNames, data);                                                         
tt.printTable();   

Die API ermöglicht auch das Sortieren und Zeilennummerieren ...

daniel_or_else
quelle
1
Dies ist eine Art Schmerz, aber es ist schöner, als die Formatierung der Zeichenfolgen kontinuierlich anzupassen. Es wäre sogar noch besser, wenn: - das
Quellglas
15

Ich habe ein Projekt erstellt, mit dem sehr erweiterte Tabellenansichten erstellt werden können. Wenn Sie die Tabelle drucken möchten, ist die Breite der Tabelle begrenzt. Ich habe es in einem meiner eigenen Projekte angewendet, um einen Kundenrechnungsdruck zu erhalten. Es folgt ein Beispiel für die Druckansicht.

           PLATINUM COMPUTERS(PVT) LTD          
     NO 20/B, Main Street, Kandy, Sri Lanka.    
  Land: 812254630 Mob: 712205220 Fax: 812254639 

                CUSTOMER INVOICE                

+-----------------------+----------------------+
|INFO                   |CUSTOMER              |
+-----------------------+----------------------+
|DATE: 2015-9-8         |ModernTec Distributors|
|TIME: 10:53:AM         |MOB: +94719530398     |
|BILL NO: 12            |ADDRES: No 25, Main St|
|INVOICE NO: 458-80-108 |reet, Kandy.          |
+-----------------------+----------------------+
|                SELLING DETAILS               |
+-----------------+---------+-----+------------+
|ITEM             | PRICE($)|  QTY|       VALUE|
+-----------------+---------+-----+------------+
|Optical mouse    |   120.00|   20|     2400.00|
|Gaming keyboard  |   550.00|   30|    16500.00|
|320GB SATA HDD   |   220.00|   32|     7040.00|
|500GB SATA HDD   |   274.00|   13|     3562.00|
|1TB SATA HDD     |   437.00|   11|     4807.00|
|RE-DVD ROM       |   144.00|   29|     4176.00|
|DDR3 4GB RAM     |   143.00|   13|     1859.00|
|Blu-ray DVD      |    94.00|   28|     2632.00|
|WR-DVD           |   122.00|   34|     4148.00|
|Adapter          |   543.00|   28|    15204.00|
+-----------------+---------+-----+------------+
|               RETURNING DETAILS              |
+-----------------+---------+-----+------------+
|ITEM             | PRICE($)|  QTY|       VALUE|
+-----------------+---------+-----+------------+
|320GB SATA HDD   |   220.00|    4|      880.00|
|WR-DVD           |   122.00|    7|      854.00|
|1TB SATA HDD     |   437.00|    7|     3059.00|
|RE-DVD ROM       |   144.00|    4|      576.00|
|Gaming keyboard  |   550.00|    6|     3300.00|
|DDR3 4GB RAM     |   143.00|    7|     1001.00|
+-----------------+---------+-----+------------+
                              GROSS   59,928.00 
                       DISCOUNT(5%)    2,996.40 
                             RETURN    9,670.00 
                            PAYABLE   47,261.60 
                               CASH   20,000.00 
                             CHEQUE   15,000.00 
                    CREDIT(BALANCE)   12,261.60 






  ---------------------   --------------------- 
     CASH COLLECTOR         GOODS RECEIVED BY   

             soulution by clough.com            

Dies ist der Code für die obige Druckansicht. Die Bibliothek (Wagu) finden Sie hier .

CLOUGH
quelle
1
Herr @CLOUGH, ich habe Ihre Antworten sehr geschätzt. Es ist eine großartige Möglichkeit, eine Rechnung zu erstellen. Ich arbeite auch an einem Projekt, aber ich möchte nicht, dass der Abschnitt RÜCKGABEDETAIL in meiner Rechnung enthalten ist. Können Sie mir dabei helfen? Ich kann diesen Abschnitt nicht schneiden
Rafi Abro
1
@LZH - Ja, das funktioniert gut. Sie müssen jedoch die Schriftart von TextArea in Monospace ändern .
CLOUGH
1
Wird es im zentralen Maven-Repository veröffentlicht?
Hubbitus
1
Planen Sie das?
Hubbitus
1
@ Hubbitus, Eigentlich plane ich, die Logik dieser Bibliothek neu zu programmieren. Nach all dem werde ich dies auf maven veröffentlichen.
CLOUGH
13

Ich kann sehr spät für die Antwort sein, aber hier eine einfache und allgemeine Lösung

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

public class TableGenerator {

    private int PADDING_SIZE = 2;
    private String NEW_LINE = "\n";
    private String TABLE_JOINT_SYMBOL = "+";
    private String TABLE_V_SPLIT_SYMBOL = "|";
    private String TABLE_H_SPLIT_SYMBOL = "-";

    public String generateTable(List<String> headersList, List<List<String>> rowsList,int... overRiddenHeaderHeight)
    {
        StringBuilder stringBuilder = new StringBuilder();

        int rowHeight = overRiddenHeaderHeight.length > 0 ? overRiddenHeaderHeight[0] : 1; 

        Map<Integer,Integer> columnMaxWidthMapping = getMaximumWidhtofTable(headersList, rowsList);

        stringBuilder.append(NEW_LINE);
        stringBuilder.append(NEW_LINE);
        createRowLine(stringBuilder, headersList.size(), columnMaxWidthMapping);
        stringBuilder.append(NEW_LINE);


        for (int headerIndex = 0; headerIndex < headersList.size(); headerIndex++) {
            fillCell(stringBuilder, headersList.get(headerIndex), headerIndex, columnMaxWidthMapping);
        }

        stringBuilder.append(NEW_LINE);

        createRowLine(stringBuilder, headersList.size(), columnMaxWidthMapping);


        for (List<String> row : rowsList) {

            for (int i = 0; i < rowHeight; i++) {
                stringBuilder.append(NEW_LINE);
            }

            for (int cellIndex = 0; cellIndex < row.size(); cellIndex++) {
                fillCell(stringBuilder, row.get(cellIndex), cellIndex, columnMaxWidthMapping);
            }

        }

        stringBuilder.append(NEW_LINE);
        createRowLine(stringBuilder, headersList.size(), columnMaxWidthMapping);
        stringBuilder.append(NEW_LINE);
        stringBuilder.append(NEW_LINE);

        return stringBuilder.toString();
    }

    private void fillSpace(StringBuilder stringBuilder, int length)
    {
        for (int i = 0; i < length; i++) {
            stringBuilder.append(" ");
        }
    }

    private void createRowLine(StringBuilder stringBuilder,int headersListSize, Map<Integer,Integer> columnMaxWidthMapping)
    {
        for (int i = 0; i < headersListSize; i++) {
            if(i == 0)
            {
                stringBuilder.append(TABLE_JOINT_SYMBOL);   
            }

            for (int j = 0; j < columnMaxWidthMapping.get(i) + PADDING_SIZE * 2 ; j++) {
                stringBuilder.append(TABLE_H_SPLIT_SYMBOL);
            }
            stringBuilder.append(TABLE_JOINT_SYMBOL);
        }
    }


    private Map<Integer,Integer> getMaximumWidhtofTable(List<String> headersList, List<List<String>> rowsList)
    {
        Map<Integer,Integer> columnMaxWidthMapping = new HashMap<>();

        for (int columnIndex = 0; columnIndex < headersList.size(); columnIndex++) {
            columnMaxWidthMapping.put(columnIndex, 0);
        }

        for (int columnIndex = 0; columnIndex < headersList.size(); columnIndex++) {

            if(headersList.get(columnIndex).length() > columnMaxWidthMapping.get(columnIndex))
            {
                columnMaxWidthMapping.put(columnIndex, headersList.get(columnIndex).length());
            }
        }


        for (List<String> row : rowsList) {

            for (int columnIndex = 0; columnIndex < row.size(); columnIndex++) {

                if(row.get(columnIndex).length() > columnMaxWidthMapping.get(columnIndex))
                {
                    columnMaxWidthMapping.put(columnIndex, row.get(columnIndex).length());
                }
            }
        }

        for (int columnIndex = 0; columnIndex < headersList.size(); columnIndex++) {

            if(columnMaxWidthMapping.get(columnIndex) % 2 != 0)
            {
                columnMaxWidthMapping.put(columnIndex, columnMaxWidthMapping.get(columnIndex) + 1);
            }
        }


        return columnMaxWidthMapping;
    }

    private int getOptimumCellPadding(int cellIndex,int datalength,Map<Integer,Integer> columnMaxWidthMapping,int cellPaddingSize)
    {
        if(datalength % 2 != 0)
        {
            datalength++;
        }

        if(datalength < columnMaxWidthMapping.get(cellIndex))
        {
            cellPaddingSize = cellPaddingSize + (columnMaxWidthMapping.get(cellIndex) - datalength) / 2;
        }

        return cellPaddingSize;
    }

    private void fillCell(StringBuilder stringBuilder,String cell,int cellIndex,Map<Integer,Integer> columnMaxWidthMapping)
    {

        int cellPaddingSize = getOptimumCellPadding(cellIndex, cell.length(), columnMaxWidthMapping, PADDING_SIZE);

        if(cellIndex == 0)
        {
            stringBuilder.append(TABLE_V_SPLIT_SYMBOL); 
        }

        fillSpace(stringBuilder, cellPaddingSize);
        stringBuilder.append(cell);
        if(cell.length() % 2 != 0)
        {
            stringBuilder.append(" ");
        }

        fillSpace(stringBuilder, cellPaddingSize);

        stringBuilder.append(TABLE_V_SPLIT_SYMBOL); 

    }

    public static void main(String[] args) {
        TableGenerator tableGenerator = new TableGenerator();

        List<String> headersList = new ArrayList<>(); 
        headersList.add("Id");
        headersList.add("F-Name");
        headersList.add("L-Name");
        headersList.add("Email");

        List<List<String>> rowsList = new ArrayList<>();

        for (int i = 0; i < 5; i++) {
            List<String> row = new ArrayList<>(); 
            row.add(UUID.randomUUID().toString());
            row.add(UUID.randomUUID().toString());
            row.add(UUID.randomUUID().toString());
            row.add(UUID.randomUUID().toString());

            rowsList.add(row);
        }

        System.out.println(tableGenerator.generateTable(headersList, rowsList));
    }
}

Mit dieser Art von Ausgabe

+----------------------------------------+----------------------------------------+----------------------------------------+----------------------------------------+
|                   Id                   |                F-Name                  |                 L-Name                 |                  Email                 |
+----------------------------------------+----------------------------------------+----------------------------------------+----------------------------------------+
|  70a56f25-d42a-499c-83ac-50188c45a0ac  |  aa04285e-c135-46e2-9f90-988bf7796cd0  |  ac495ba7-d3c7-463c-8c24-9ffde67324bc  |  f6b5851b-41e0-4a4e-a237-74f8e0bff9ab  |
|  6de181ca-919a-4425-a753-78d2de1038ef  |  c4ba5771-ccee-416e-aebd-ef94b07f4fa2  |  365980cb-e23a-4513-a895-77658f130135  |  69e01da1-078e-4934-afb0-5afd6ee166ac  |
|  f3285f33-5083-4881-a8b4-c8ae10372a6c  |  46df25ed-fa0f-42a4-9181-a0528bc593f6  |  d24016bf-a03f-424d-9a8f-9a7b7388fd85  |  4b976794-aac1-441e-8bd2-78f5ccbbd653  |
|  ab799acb-a582-45e7-ba2f-806948967e6c  |  d019438d-0a75-48bc-977b-9560de4e033e  |  8cb2ad11-978b-4a67-a87e-439d0a21ef99  |  2f2d9a39-9d95-4a5a-993f-ceedd5ff9953  |
|  78a68c0a-a824-42e8-b8a8-3bdd8a89e773  |  0f030c1b-2069-4c1a-bf7d-f23d1e291d2a  |  7f647cb4-a22e-46d2-8c96-0c09981773b1  |  0bc944ef-c1a7-4dd1-9eef-915712035a74  |
+----------------------------------------+----------------------------------------+----------------------------------------+----------------------------------------+
Naval Kishore
quelle
Die einzigen Importe, die Sie benötigen, sind: import java.util.HashMap; import java.util.List; import java.util.Map;
Jake Hm
Wäre nicht schlecht, wenn Sie eine öffentliche statische Leere mit einem tatsächlichen Beispiel hätten versehen können.
mmm
1
Diese Lösung kann nicht als "einfach" bezeichnet werden
Gauraang Khurana
11

Überprüfen Sie dies heraus. Der Autor bietet eine einfache, aber elegante Lösung, für die keine Bibliothek von Drittanbietern erforderlich ist. http://www.ksmpartners.com/2013/08/nicely-formatted-tabular-output-in-java/

Ein Beispiel für den TableBuilder und die Beispielausgabe

Mingjiang Shi
quelle
Diese Lösung verwende ich sehr gut mit einer Bibliothek von Drittanbietern: Apache Lang Aber immer noch die beste Lösung für meine Bedürfnisse. 1+
Spenhouet
Das Kopieren von Streucode aus dem Internet ist tatsächlich etwas schlechter als eine Bibliothek eines Drittanbieters. Es ist eine Bibliothek, die niemand verpackt hat, damit andere sie wiederverwenden können.
Greg Chabala
7

Da die meisten Lösungen etwas veraltet sind, könnte ich auch asciitable vorschlagen, die bereits in maven verfügbar sind (de.vandermeer:asciitable:0.3.2 ) und möglicherweise sehr komplizierte Konfigurationen erzeugen.

Funktionen (von außerhalb):

  • Texttabelle mit einiger Flexibilität für Regeln und Inhalt, Ausrichtung, Format, Auffüllung, Ränder und Rahmen:
  • Hinzufügen von Text, so oft wie erforderlich in vielen verschiedenen Formaten (Zeichenfolge, Textanbieter, Renderanbieter, ST, Cluster),
  • entfernt alle übermäßigen Leerzeichen (Tabulatoren, zusätzliche Leerzeichen, Kombinationen aus Wagenrücklauf und Zeilenvorschub),
  • 6 verschiedene Textausrichtungen: links, rechts, zentriert, ausgerichtet, gerechtfertigt letzte Zeile links, rechts letzte Zeile rechts,
  • flexible Breite, für Text festgelegt und auf viele verschiedene Arten für das Rendern berechnet
  • Füllzeichen für linkes und rechtes Auffüllen (separat konfigurierbar)
  • Auffüllzeichen für obere und untere Auffüllung (separat konfigurierbar)
  • verschiedene Optionen zum Zeichnen von Gittern
  • Regeln mit unterschiedlichen Stilen (wie vom verwendeten Rasterthema unterstützt: normal, leicht, stark, schwer)
  • obere / untere / linke / rechte Ränder außerhalb eines Rahmens
  • Zeichenkonvertierung in generierten Text, der für die weitere Verarbeitung geeignet ist, z. B. für LaTeX und HTML

Und die Verwendung sieht immer noch einfach aus:

AsciiTable at = new AsciiTable();

at.addRule();
at.addRow("row 1 col 1", "row 1 col 2");
at.addRule();
at.addRow("row 2 col 1", "row 2 col 2");
at.addRule();

System.out.println(at.render()); // Finally, print the table to standard out.
Hubbitus
quelle
2
Schöne und gut dokumentierte Bibliothek
David Lilljegren
3
public class Main {
 public static void main(String args[]) {
   String format = "|%1$-10s|%2$-10s|%3$-20s|\n";
   System.out.format(format, "A", "AA", "AAA");
   System.out.format(format, "B", "", "BBBBB");
   System.out.format(format, "C", "CCCCC", "CCCCCCCC");

   String ex[] = { "E", "EEEEEEEEEE", "E" };

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

Unterschiedliche Eingangsgrößen wirken sich nicht auf die Ausgabe aus

Manoj Jangam
quelle