Salida en formato de tabla en System.out de Java

Respuestas:

145

Utilice System.out.format. Puede establecer longitudes de campos como este:

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

Esto rellena string1, int1y string2hasta 32, 10 y 16 caracteres, respectivamente.

Consulte los Javadocs para java.util.Formatterobtener más información sobre la sintaxis ( System.out.formatutiliza Formatterinternamente).

Michael Myers
fuente
1
¡Gracias justo lo que necesitaba! Solo agregaré que necesitaba poner \ n al final para producir una nueva línea cada vez, en caso de que alguien más encuentre ese problema.
Chris
19
O, mejor, un %n- se traduce automáticamente al terminador de línea predeterminado del sistema.
Michael Myers
1
¿Cómo podría hacer la alineación a la izquierda en la tabla de cuerdas?
Mike
16
Alineación a la izquierda: System.out.format ("% - 2s% 10d% -16s", cadena1, int1, cadena2);
Mike
1
Si quiero alinearlo en el centro, ¿cómo hacerlo?
pratnala
36

Usando j-text-utils puede imprimir para consolar una tabla como: ingrese la descripción de la imagen aquí

Y es tan simple como:

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

La API también permite ordenar y numerar filas ...

daniel_or_else
fuente
1
Es un poco complicado de usar, pero es mejor que ajustar continuamente el formato de cadena. Sería incluso mejor si: - el jar de origen se publicara en el repositorio de Maven - estuviera en un repositorio muy conocido como Central
Greg Chabala
15

He creado un proyecto que puede crear vistas de tabla muy avanzadas. Si se supone que debe imprimir la tabla, el ancho de la tabla tendrá un límite. Lo he aplicado en uno de mis propios proyectos para obtener una impresión de la factura del cliente. A continuación se muestra un ejemplo de la vista de impresión.

           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            

Este es el código para la vista de impresión anterior y puede encontrar la biblioteca (Wagu) aquí .

CLOUGH
fuente
1
Sr. @CLOUGH, realmente aprecio sus respuestas. es una excelente manera de generar facturas ... también estoy trabajando en un proyecto, pero no quiero DETALLAR DEVOLUCIÓN de la sección en mi factura ... ¿pueden ayudarme con esto ... No puedo cortar esta sección
Rafi Abro
1
@LZH - Sí, esto funciona bien. Pero, debe cambiar el tipo de letra de TextArea a Monospace .
CLOUGH
1
¿Se publica en el repositorio central de maven?
Hubbitus
1
¿Planeas hacer eso?
Hubbitus
1
@Hubbitus, en realidad planeo reprogramar la lógica de esta biblioteca. Después de todo eso, publicaré esto en Maven.
CLOUGH
15

Puede que llegue muy tarde para la respuesta, pero aquí hay una solución simple y genérica.

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

Con este tipo de salida

+----------------------------------------+----------------------------------------+----------------------------------------+----------------------------------------+
|                   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  |
+----------------------------------------+----------------------------------------+----------------------------------------+----------------------------------------+
Kishore naval
fuente
Las únicas importaciones que necesita son: import java.util.HashMap; import java.util.List; import java.util.Map;
Jake Hm
No estaría mal si pudiera haber proporcionado un principal vacío estático público con un ejemplo real.
mmm
1
Esta solución no se puede llamar "simple"
Gauraang Khurana
11

Mira esto. El autor proporciona una solución simple pero elegante que no requiere ninguna biblioteca de terceros. http://www.ksmpartners.com/2013/08/nicely-formatted-tabular-output-in-java/

Un ejemplo de TableBuilder y salida de muestra

Mingjiang Shi
fuente
Esta solución utilizo muy bien una biblioteca de terceros: Apache Lang, pero sigue siendo la mejor solución para mis necesidades. 1+
Spenhouet
Copiar código perdido de Internet es en realidad un poco peor que una biblioteca de terceros; es una biblioteca que nadie se molestó en empaquetar para que otros la reutilizaran.
Greg Chabala
7

Debido a que la mayoría de las soluciones están un poco desactualizadas, también podría sugerir asciitable que ya está disponible en maven ( de.vandermeer:asciitable:0.3.2) y puede producir configuraciones muy complicadas.

Características (por fuera del sitio):

  • Tabla de texto con cierta flexibilidad para reglas y contenido, alineación, formato, relleno, márgenes y marcos:
  • agregar texto, tantas veces como sea necesario, en muchos formatos diferentes (cadena, proveedor de texto, proveedor de renderizado, ST, clústeres),
  • elimina todos los espacios en blanco excesivos (tabuladores, espacios en blanco adicionales, combinaciones de retorno de carro y salto de línea),
  • 6 alineaciones de texto diferentes: izquierda, derecha, centrada, justificada, última línea justificada a la izquierda, última línea justificada a la derecha,
  • ancho flexible, configurado para texto y calculado de muchas formas diferentes para renderizar
  • caracteres de relleno para relleno izquierdo y derecho (configurable por separado)
  • caracteres de relleno para el relleno superior e inferior (configurable por separado)
  • varias opciones para dibujar cuadrículas
  • reglas con diferentes estilos (como lo admite el tema de cuadrícula utilizado: normal, ligero, fuerte, pesado)
  • márgenes superior / inferior / izquierdo / derecho fuera de un marco
  • conversión de caracteres en texto generado adecuado para procesos posteriores, por ejemplo, para LaTeX y HTML

Y el uso todavía parece fácil:

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
fuente
2
Biblioteca agradable y bien documentada
David Lilljegren
5
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 diferencia en los tamaños de entrada no afecta la salida

manoj jangam
fuente