เอาต์พุตในรูปแบบตารางใน System.out ของ Java


93

ฉันได้ผลลัพธ์จากฐานข้อมูลและต้องการส่งออกข้อมูลเป็นตารางในเอาต์พุตมาตรฐานของ Java

ฉันได้ลองใช้ \ t แล้ว แต่คอลัมน์แรกที่ฉันต้องการมีความยาวแปรผันมาก

มีวิธีแสดงสิ่งนี้ในตารางที่ดีเช่นเอาต์พุตหรือไม่?


คำตอบ:


149

ใช้System.out.format. คุณสามารถกำหนดความยาวของฟิลด์ได้ดังนี้:

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

แผ่นนี้string1, int1และstring232, 10, และ 16 ตัวอักษรตามลำดับ

ดู Javadocs สำหรับjava.util.Formatterข้อมูลเพิ่มเติมเกี่ยวกับไวยากรณ์ ( System.out.formatใช้Formatterภายใน)


1
ขอบคุณสิ่งที่ฉันต้องการ! ฉันจะเพิ่มฉันต้องใส่ \ n ต่อท้ายเพื่อสร้างบรรทัดใหม่ทุกครั้งเผื่อว่ามีใครพบปัญหานั้น
คริส

20
หรือที่ดีกว่านั้น a %n- มันจะถูกแปลเป็นตัวยุติบรรทัดเริ่มต้นของระบบโดยอัตโนมัติ
Michael Myers

1
ฉันจะจัดตำแหน่งซ้ายในตารางสตริงได้อย่างไร
Mike

16
จัดชิดซ้าย: System.out.format ("% - 2s% 10d% -16s", string1, int1, string2);
Mike

1
ถ้าต้องการจัดกึ่งกลางต้องทำอย่างไร?
pratnala

37

การใช้j-text-utilsคุณสามารถพิมพ์เพื่อคอนโซลตารางเช่น: ใส่คำอธิบายภาพที่นี่

และง่ายเหมือน:

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

API ยังอนุญาตการเรียงลำดับและการกำหนดหมายเลขแถว ...


1
นี่เป็นความเจ็บปวดที่จะใช้ แต่ก็ดีกว่าการปรับการจัดรูปแบบสตริงอย่างต่อเนื่อง จะดีกว่านี้ถ้า: - โถต้นทางถูกเผยแพร่ไปยัง Maven repo - อยู่ใน repo ที่รู้จักกันดีเช่น Central
Greg Chabala

16

ฉันได้สร้างโครงการที่สามารถสร้างมุมมองตารางขั้นสูงได้ หากคุณควรพิมพ์ตารางความกว้างของตารางจะมีขีด จำกัด ฉันได้นำไปใช้ในโครงการของตัวเองเพื่อพิมพ์ใบแจ้งหนี้ของลูกค้า ต่อไปนี้เป็นตัวอย่างของมุมมองการพิมพ์

           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            

นี้เป็นรหัสสำหรับมุมมองการพิมพ์ข้างต้นและคุณสามารถหาห้องสมุด (Wagu) ในที่นี่


1
นาย @CLOUGH ฉันชอบคำตอบของคุณมาก เป็นวิธีที่ยอดเยี่ยมในการสร้างใบแจ้งหนี้ .. ฉันกำลังทำโปรเจ็กต์อยู่ แต่ฉันไม่ต้องการส่วนรายละเอียดการส่งคืนในใบแจ้งหนี้ของฉัน ... คุณช่วยฉันผ่านเรื่องนี้ได้ไหม .. ฉันไม่สามารถตัดส่วนนี้ได้
Rafi Abro

1
@LZH - ใช่มันใช้งานได้ดี แต่คุณจำเป็นต้องเปลี่ยนแบบอักษรของ TextArea ไปMonospace
CLOUGH

1
เผยแพร่ลงในที่เก็บส่วนกลางของ maven หรือไม่
Hubbitus

1
คุณวางแผนที่จะทำเช่นนั้นหรือไม่?
Hubbitus

1
@ ฮับบิตัสฉันวางแผนที่จะตั้งโปรแกรมตรรกะของห้องสมุดนี้ใหม่ หลังจากนั้นฉันจะเผยแพร่สิ่งนี้บน maven
CLOUGH

15

ฉันอาจจะสายมากสำหรับคำตอบ แต่นี่เป็นวิธีง่ายๆและทั่วไป

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

ด้วย Output แบบนี้

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

การนำเข้าเพียงอย่างเดียวที่คุณต้องการคือ import java.util.HashMap; นำเข้า java.util.List; นำเข้า java.util.Map;
Jake Hm

คงไม่แย่นักถ้าคุณสามารถให้ public static void main พร้อมตัวอย่างจริงได้
mmm

3
วิธีนี้ไม่สามารถเรียกได้ว่า "ง่าย"
Gauraang Khurana

11

ลองดู. ผู้เขียนนำเสนอโซลูชันที่เรียบง่าย แต่สวยงามซึ่งไม่ต้องการไลบรารีของบุคคลที่สาม http://www.ksmpartners.com/2013/08/nicely-formatted-tabular-output-in-java/

ตัวอย่างของ TableBuilder และเอาต์พุตตัวอย่าง


วิธีนี้ฉันทำได้ดีมากโดยใช้ไลบรารีของบุคคลที่สาม: Apache Lang แต่ก็ยังเป็นทางออกที่ดีที่สุดสำหรับความต้องการของฉัน 1+
Spenhouet

การคัดลอกรหัสหลงทางจากอินเทอร์เน็ตนั้นแย่กว่าไลบรารีของบุคคลที่สามเล็กน้อย มันเป็นห้องสมุดที่ไม่มีใครใส่ใจในการจัดแพ็กเกจเพื่อให้ผู้อื่นนำกลับมาใช้
Greg Chabala

8

เนื่องจากโซลูชันส่วนใหญ่ค่อนข้างล้าสมัยฉันจึงสามารถแนะนำasciitableซึ่งมีอยู่แล้วใน maven ( de.vandermeer:asciitable:0.3.2) และอาจสร้างการกำหนดค่าที่ซับซ้อนมาก

คุณสมบัติ (โดยนอกสถานที่):

  • ตารางข้อความที่มีความยืดหยุ่นสำหรับกฎและเนื้อหาการจัดแนวรูปแบบช่องว่างระยะขอบและเฟรม:
  • เพิ่มข้อความได้บ่อยเท่าที่ต้องการในรูปแบบต่างๆ (สตริงตัวให้บริการข้อความผู้ให้บริการการแสดงผล ST คลัสเตอร์)
  • ลบช่องว่างสีขาวที่มากเกินไปทั้งหมด (แถบตาราง, ช่องว่างเพิ่มเติม, การรวมกันของการส่งคืนแคร่และการป้อนบรรทัด)
  • การจัดแนวข้อความที่แตกต่างกัน 6 แบบ: ซ้าย, ขวา, กึ่งกลาง, ธรรม, บรรทัดสุดท้ายที่ถูกต้องทางซ้าย, บรรทัดสุดท้ายที่ถูกต้อง,
  • ความกว้างที่ยืดหยุ่นตั้งค่าสำหรับข้อความและคำนวณในรูปแบบต่างๆสำหรับการแสดงผล
  • อักขระช่องว่างสำหรับช่องว่างด้านซ้ายและด้านขวา (กำหนดค่าแยกกันได้)
  • อักขระช่องว่างสำหรับช่องว่างด้านบนและด้านล่าง (กำหนดค่าแยกกันได้)
  • หลายตัวเลือกสำหรับการวาดเส้นกริด
  • กฎที่มีสไตล์แตกต่างกัน (ตามที่ธีมกริดที่ใช้รองรับ: ปกติเบาแข็งแรงหนัก)
  • ระยะขอบบน / ล่าง / ซ้าย / ขวานอกกรอบ
  • การแปลงอักขระเป็นข้อความที่สร้างขึ้นเหมาะสำหรับกระบวนการต่อไปเช่น LaTeX และ HTML

และการใช้งานยังดูง่าย:

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.

3
ห้องสมุดที่ดีและมีเอกสารดี
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));
 }
}

ความแตกต่างของขนาดอินพุตไม่ส่งผลต่อเอาต์พุต


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.