Sortie dans un format de table dans System.out de Java

89

J'obtiens les résultats d'une base de données et je souhaite afficher les données sous forme de tableau dans la sortie standard de Java

J'ai essayé d'utiliser \ t mais la première colonne que je veux est de longueur très variable.

Y a-t-il un moyen d'afficher cela dans un joli tableau comme la sortie?

Chris
la source

Réponses:

145

Utilisez System.out.format. Vous pouvez définir des longueurs de champs comme ceci:

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

Ces plots string1, int1et string2à 32, 10 et 16 caractères, respectivement.

Voir les Javadocs pour java.util.Formatterplus d'informations sur la syntaxe ( System.out.formatutilise un en Formatterinterne).

Michael Myers
la source
1
Merci juste ce dont j'avais besoin! J'ajouterai simplement que j'avais besoin de mettre \ n à la fin pour produire une nouvelle ligne à chaque fois, au cas où quelqu'un d'autre trouverait ce problème.
Chris
19
Ou, mieux, a %n- il est automatiquement traduit en terminateur de ligne par défaut du système.
Michael Myers
1
Comment puis-je faire un alignement à gauche dans une table de chaînes?
Mike
15
Alignement à gauche: System.out.format ("% - 2s% 10d% -16s", string1, int1, string2);
Mike
1
Si je veux l'aligner au centre, comment le faire?
pratnala
36

Utilisation de j-text-utils vous pouvez imprimer pour consolider une table comme: entrez la description de l'image ici

Et c'est aussi simple que:

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

L'API permet également le tri et la numérotation des lignes ...

daniel_or_else
la source
1
C'est un peu pénible à utiliser, mais c'est plus agréable que d'ajuster continuellement le formatage des chaînes. Ce serait encore mieux si: - le jar source était publié dans le repo Maven - il était dans un repo bien connu comme Central
Greg Chabala
15

J'ai créé un projet qui peut créer des vues de table beaucoup plus avancées. Si vous êtes censé imprimer le tableau, la largeur du tableau aura une limite. Je l'ai appliqué dans l'un de mes propres projets pour imprimer une facture client. Voici un exemple de la vue d'impression.

           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            

Ceci est le code pour la vue d'impression ci-dessus et vous pouvez trouver la bibliothèque (Wagu) ici .

NUAGE
la source
1
M. @CLOUGH, j'ai vraiment apprécié vos réponses. c'est un excellent moyen de générer une facture .. je travaille également sur un projet mais je ne veux pas de section RETOUR DE DÉTAIL dans ma facture ... pouvez-vous m'aider à travers cela .. Je ne peux pas couper cette section
Rafi Abro
1
@LZH - Oui, cela fonctionne bien. Mais, vous devez changer la police de caractères de TextArea en Monospace .
CLOUGH
1
Est-il publié dans le référentiel central maven?
Hubbitus
1
Avez-vous l'intention de faire cela?
Hubbitus
1
@Hubbitus, En fait, je prévois de reprogrammer la logique de cette bibliothèque. Après tout cela, je publierai ceci sur maven.
CLOUGH
15

Je suis peut-être très en retard pour la réponse mais voici une solution simple et générique

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));
    }
}

Avec ce type de sortie

+----------------------------------------+----------------------------------------+----------------------------------------+----------------------------------------+
|                   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
la source
Les seules importations dont vous avez besoin sont: import java.util.HashMap; import java.util.List; import java.util.Map;
Jake Hm
Ce ne serait pas mal si vous aviez pu fournir un principal vide statique public avec un exemple réel.
mmm
1
Cette solution ne peut pas être qualifiée de «simple»
Gauraang Khurana
11

Regarde ça. L'auteur propose une solution simple mais élégante qui ne nécessite aucune bibliothèque tierce. http://www.ksmpartners.com/2013/08/nicely-formatted-tabular-output-in-java/

Un exemple de TableBuilder et un exemple de sortie

Mingjiang Shi
la source
Cette solution utilise très bien une bibliothèque tierce: Apache Lang Mais toujours la meilleure solution pour mon besoin. 1+
Spenhouet
La copie de code parasite à partir d'Internet est en fait légèrement pire qu'une bibliothèque tierce; c'est une bibliothèque que personne n'a même pris la peine d'empaqueter pour que d'autres puissent la réutiliser.
Greg Chabala
7

Parce que la plupart des solutions sont un peu obsolètes, je pourrais également suggérer asciitable qui est déjà disponible dans maven ( de.vandermeer:asciitable:0.3.2) et peut produire des configurations très compliquées.

Caractéristiques (hors site):

  • Tableau de texte avec une certaine flexibilité pour les règles et le contenu, l'alignement, le format, le remplissage, les marges et les cadres:
  • ajouter du texte, aussi souvent que nécessaire dans de nombreux formats différents (chaîne, fournisseur de texte, fournisseur de rendu, ST, clusters),
  • supprime tous les espaces blancs excessifs (tabulateurs, blancs supplémentaires, combinaisons de retour chariot et saut de ligne),
  • 6 alignements de texte différents: gauche, droite, centré, justifié, justifié dernière ligne à gauche, justifié dernière ligne droite,
  • largeur flexible, définie pour le texte et calculée de différentes manières pour le rendu
  • caractères de remplissage pour le remplissage gauche et droit (configurables séparément)
  • caractères de remplissage pour le remplissage supérieur et inférieur (configurables séparément)
  • plusieurs options pour dessiner des grilles
  • règles avec différents styles (comme pris en charge par le thème de grille utilisé: normal, léger, fort, lourd)
  • marges haut / bas / gauche / droite à l'extérieur d'un cadre
  • conversion de caractères en texte généré adapté à un processus ultérieur, par exemple pour LaTeX et HTML

Et l'utilisation semble toujours facile:

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
la source
2
Belle bibliothèque bien documentée
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));
 }
}

la différence de taille d'entrée n'affecte pas la sortie

manoj jangam
la source