Đầu ra ở định dạng bảng trong System.out của Java


89

Tôi đang nhận kết quả từ cơ sở dữ liệu và muốn xuất dữ liệu dưới dạng bảng trong đầu ra chuẩn của Java

Tôi đã thử sử dụng \ t nhưng cột đầu tiên tôi muốn có độ dài rất thay đổi.

Có cách nào để hiển thị điều này trong một bảng đẹp như đầu ra không?


Câu trả lời:


145

Sử dụng System.out.format. Bạn có thể đặt độ dài của các trường như sau:

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

Miếng đệm này string1, int1string2đến 32, 10, và 16 ký tự, tương ứng.

Xem Javadocs để java.util.Formatterbiết thêm thông tin về cú pháp ( System.out.formatsử dụng Formatternội bộ).


1
Cảm ơn chỉ những gì tôi cần! Tôi sẽ chỉ thêm tôi cần đặt \ n vào cuối để tạo một dòng mới mỗi lần, trong trường hợp bất kỳ ai khác phát hiện ra vấn đề đó.
Chris

19
Hoặc, tốt hơn, a %n- nó sẽ được tự động dịch sang trình kết thúc dòng mặc định của hệ thống.
Michael Myers

1
Làm cách nào tôi có thể căn lề trái trong bảng chuỗi?
Mike

15
Căn trái: System.out.format ("% - 2s% 10d% -16s", string1, int1, string2);
Mike

1
Nếu tôi muốn căn giữa nó thì phải làm như thế nào?
pratnala

36

Sử dụng j-text-utils, bạn có thể in ra bảng điều khiển như: nhập mô tả hình ảnh ở đây

Và nó đơn giản như:

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

API cũng cho phép sắp xếp và đánh số hàng ...


1
Điều này hơi khó sử dụng, nhưng nó đẹp hơn là liên tục điều chỉnh định dạng chuỗi. Nó muốn được tốt hơn nếu: - jar nguồn được công bố vào Maven repo - đó là một trong repo nổi tiếng như Central
Greg Chabala

15

Tôi đã tạo một dự án có thể xây dựng các chế độ xem bảng nâng cao. Nếu bạn phải in bảng, chiều rộng của bảng sẽ có giới hạn. Tôi đã áp dụng nó trong một trong những dự án của riêng mình để lấy hóa đơn in cho khách hàng. Sau đây là một ví dụ về chế độ xem in.

           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            

Đây là mã cho chế độ xem bản in ở trên và bạn có thể tìm thấy thư viện (Wagu) tại đây .


1
Ông @CLOUGH, tôi thực sự đánh giá cao câu trả lời của bạn. Đó là một cách tuyệt vời để tạo hóa đơn .. tôi cũng đang làm dự án nhưng tôi không muốn phần TRẢ LẠI CHI TIẾT trong hóa đơn của mình ... bạn có thể giúp tôi phần này không .. Tôi không thể cắt phần này
Rafi Abro

1
@LZH - Có, điều này hoạt động tốt. Tuy nhiên, bạn cần thay đổi kiểu chữ của TextArea thành Monospace .
ĐÓNG

1
Nó có được xuất bản vào kho lưu trữ trung tâm maven không?
Hubbitus

1
Bạn có kế hoạch làm điều đó?
Hubbitus

1
@Hubbitus, Thực ra tôi đang định lập trình lại logic của thư viện này. Sau tất cả những điều đó, tôi sẽ xuất bản nó trên maven.
CLOUGH

14

Tôi có thể đến rất muộn để có Câu trả lời nhưng đây là một giải pháp đơn giản và chung chung

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

Với loại đầu ra này

+----------------------------------------+----------------------------------------+----------------------------------------+----------------------------------------+
|                   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  |
+----------------------------------------+----------------------------------------+----------------------------------------+----------------------------------------+

Các nhập duy nhất bạn cần là: import java.util.HashMap; nhập java.util.List; nhập java.util.Map;
Jake Hm

Sẽ không tồi nếu bạn có thể cung cấp một void main công khai tĩnh với một ví dụ thực tế.
mmm

1
Giải pháp này không thể được gọi là "đơn giản"
Gauraang Khurana

11

Kiểm tra điều này. Tác giả cung cấp một giải pháp đơn giản nhưng thanh lịch mà không yêu cầu bất kỳ thư viện bên thứ ba nào. http://www.ksmpartners.com/2013/08/nicely-formatted-tabular-output-in-java/

Ví dụ về TableBuilder và đầu ra mẫu


Giải pháp này tôi rất tốt khi sử dụng thư viện của bên thứ 3: Apache Lang Nhưng vẫn là giải pháp tốt nhất cho nhu cầu của tôi. 1+
Spenhouet

Sao chép mã lạc từ internet thực sự kém hơn một chút so với thư viện của bên thứ 3; đó là một thư viện mà không ai thèm đóng gói để người khác sử dụng lại.
Greg Chabala

7

Bởi vì hầu hết các giải pháp đã lỗi thời, tôi cũng có thể đề xuất asciitable đã có sẵn trong maven ( de.vandermeer:asciitable:0.3.2) và có thể tạo ra các cấu hình rất phức tạp.

Các tính năng (bởi ngoại vi):

  • Bảng văn bản với một số tính linh hoạt cho các quy tắc và nội dung, căn chỉnh, định dạng, đệm, lề và khung:
  • thêm văn bản, thường xuyên theo yêu cầu ở nhiều định dạng khác nhau (chuỗi, trình cung cấp văn bản, trình cung cấp kết xuất, ST, cụm),
  • loại bỏ tất cả các khoảng trắng thừa (bảng biểu, khoảng trống thừa, kết hợp ký tự xuống dòng và nguồn cấp dữ liệu dòng),
  • 6 căn chỉnh văn bản khác nhau: trái, phải, căn giữa, căn đều, căn dòng cuối cùng bên trái, căn dòng cuối cùng bên phải,
  • chiều rộng linh hoạt, được đặt cho văn bản và được tính toán theo nhiều cách khác nhau để hiển thị
  • ký tự đệm cho đệm trái và phải (có thể định cấu hình riêng)
  • ký tự đệm cho phần đệm trên và dưới (có thể định cấu hình riêng)
  • một số tùy chọn để vẽ lưới
  • các quy tắc với các kiểu khác nhau (được hỗ trợ bởi chủ đề lưới đã sử dụng: bình thường, nhẹ, mạnh, nặng)
  • lề trên / dưới / trái / phải bên ngoài khung
  • chuyển đổi ký tự thành văn bản được tạo thích hợp cho quá trình tiếp theo, ví dụ: cho LaTeX và HTML

Và việc sử dụng trông vẫn dễ dàng:

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.

2
Thư viện tài liệu tốt và đẹp
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));
 }
}

sự khác biệt về kích thước của đầu vào không ảnh hưởng đến đầu ra


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.