java打印表格 將ResultSet中的數(shù)據(jù)打印成表格問題
問題描述
MySQL的查詢語句輸出如下:
mysql> select * from instructor;
+-------+------------+------------+-----------+
| ID | name | dept_name | salary |
+-------+------------+------------+-----------+
| 10101 | Srinivasan | Comp. Sci. | 65000.00 |
| 12121 | Wu | Finance | 90000.00 |
| 15151 | Mozart | Music | 40000.00 |
| 22222 | Einstein | Physics | 95000.00 |
| 25566 | Brown | Biology | 100000.00 |
| 30765 | Green | Music | NULL |
| 32343 | El Said | History | 60000.00 |
| 33456 | Gold | Physics | 87000.00 |
| 45565 | Katz | Comp. Sci. | 75000.00 |
| 58583 | Califieri | History | 62000.00 |
| 76543 | Singh | Finance | 80000.00 |
| 76766 | Crick | Biology | 72000.00 |
| 77987 | Kim | Physics | 98000.00 |
| 83821 | Brandt | Comp. Sci. | 92000.00 |
| 88877 | Perry | Finance | 125000.00 |
| 88878 | Perry | Finance | 125000.00 |
| 98345 | Kim | Elec. Eng. | 80000.00 |
+-------+------------+------------+-----------+
17 rows in set (0.04 sec)
使用JDBC執(zhí)行上述的查詢語句,將結(jié)果集中的查詢結(jié)果以表格的形式打印出來。
思路
- 通過結(jié)果集的元數(shù)據(jù)可以知道結(jié)果集中的列數(shù),和列名.
- 然后遍歷結(jié)果集,分別統(tǒng)計(jì)每一列中的最大字符數(shù)。
- 然后通過System.out.printf()方法進(jìn)行格式化輸出。
實(shí)現(xiàn)
package tools; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.util.ArrayList; import java.util.Iterator; /** * 結(jié)果集打印機(jī).將結(jié)果集中的數(shù)據(jù)打印成表格. */ public class ResultSetPrinter { public static void printResultSet(ResultSet rs) throws SQLException { ResultSetMetaData resultSetMetaData = rs.getMetaData(); // 獲取列數(shù) int ColumnCount = resultSetMetaData.getColumnCount(); // 保存當(dāng)前列最大長度的數(shù)組 int[] columnMaxLengths = new int[ColumnCount]; // 緩存結(jié)果集,結(jié)果集可能有序,所以用ArrayList保存變得打亂順序. ArrayList<String[]> results = new ArrayList<>(); // 按行遍歷 while (rs.next()) { // 保存當(dāng)前行所有列 String[] columnStr = new String[ColumnCount]; // 獲取屬性值. for (int i = 0; i < ColumnCount; i++) { // 獲取一列 columnStr[i] = rs.getString(i + 1); // 計(jì)算當(dāng)前列的最大長度 columnMaxLengths[i] = Math.max(columnMaxLengths[i], (columnStr[i] == null) ? 0 : columnStr[i].length()); } // 緩存這一行. results.add(columnStr); } printSeparator(columnMaxLengths); printColumnName(resultSetMetaData, columnMaxLengths); printSeparator(columnMaxLengths); // 遍歷集合輸出結(jié)果 Iterator<String[]> iterator = results.iterator(); String[] columnStr; while (iterator.hasNext()) { columnStr = iterator.next(); for (int i = 0; i < ColumnCount; i++) { // System.out.printf("|%" + (columnMaxLengths[i] + 1) + "s", columnStr[i]); System.out.printf("|%" + columnMaxLengths[i] + "s", columnStr[i]); } System.out.println("|"); } printSeparator(columnMaxLengths); } /** * 輸出列名. * * @param resultSetMetaData 結(jié)果集的元數(shù)據(jù)對(duì)象. * @param columnMaxLengths 每一列最大長度的字符串的長度. * @throws SQLException */ private static void printColumnName(ResultSetMetaData resultSetMetaData, int[] columnMaxLengths) throws SQLException { int columnCount = resultSetMetaData.getColumnCount(); for (int i = 0; i < columnCount; i++) { // System.out.printf("|%" + (columnMaxLengths[i] + 1) + "s", resultSetMetaData.getColumnName(i + 1)); System.out.printf("|%" + columnMaxLengths[i] + "s", resultSetMetaData.getColumnName(i + 1)); } System.out.println("|"); } /** * 輸出分隔符. * * @param columnMaxLengths 保存結(jié)果集中每一列的最長的字符串的長度. */ private static void printSeparator(int[] columnMaxLengths) { for (int i = 0; i < columnMaxLengths.length; i++) { System.out.print("+"); // for (int j = 0; j < columnMaxLengths[i] + 1; j++) { for (int j = 0; j < columnMaxLengths[i]; j++) { System.out.print("-"); } } System.out.println("+"); } }
測(cè)試
package tools; import java.sql.*; public class Test { private static String driver = "com.mysql.cj.jdbc.Driver"; private static String URL = "jdbc:mysql://127.0.0.1:3306/university?serverTimezone=UTC"; private static String user = "root"; private static String password = "root"; /** * JDBC測(cè)試. */ private static void JDBCexample() { // 1.加載數(shù)據(jù)庫驅(qū)動(dòng) try { Class.forName(driver); } catch (ClassNotFoundException e) { e.printStackTrace(); } testStatement(); } /** * 測(cè)試Statement的用法. */ private static void testStatement() { try (// 2.打開數(shù)據(jù)庫連接 Connection conn = DriverManager.getConnection(URL, user, password); // 3.創(chuàng)建語句 Statement stmt = conn.createStatement()) { // 模擬SQL注入 testSqlInjecton(stmt); } catch (SQLException sqle) { System.out.println("SQLException : " + sqle); } } /** * 模擬SQL注入. * * @param stmt Statement對(duì)象. * @throws SQLException */ private static void testSqlInjecton(Statement stmt) throws SQLException { String name = "X' or 'Y' = 'Y"; String sql = "select * from instructor where name = '" + name + "'"; ResultSet rs = stmt.executeQuery(sql); ResultSetPrinter.printResultSet(rs); } public static void main(String[] args) { JDBCexample(); } }
運(yùn)行結(jié)果
+-----+----------+----------+---------+
| ID| name| dept_name| salary|
+-----+----------+----------+---------+
|10101|Srinivasan|Comp. Sci.| 65000.00|
|12121| Wu| Finance| 90000.00|
|15151| Mozart| Music| 40000.00|
|22222| Einstein| Physics| 95000.00|
|25566| Brown| Biology|100000.00|
|30765| Green| Music| null|
|32343| El Said| History| 60000.00|
|33456| Gold| Physics| 87000.00|
|45565| Katz|Comp. Sci.| 75000.00|
|58583| Califieri| History| 62000.00|
|76543| Singh| Finance| 80000.00|
|76766| Crick| Biology| 72000.00|
|77987| Kim| Physics| 98000.00|
|83821| Brandt|Comp. Sci.| 92000.00|
|88877| Perry| Finance|125000.00|
|88878| Perry| Finance|125000.00|
|98345| Kim|Elec. Eng.| 80000.00|
+-----+----------+----------+---------+
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
springboot配置多數(shù)據(jù)源的一款框架(dynamic-datasource-spring-boot-starter
dynamic-datasource-spring-boot-starter 是一個(gè)基于 springboot 的快速集成多數(shù)據(jù)源的啟動(dòng)器,今天通過本文給大家分享這款框架配置springboot多數(shù)據(jù)源的方法,一起看看吧2021-09-09MyBatis-Plus中最簡單的查詢操作教程(Lambda)
這篇文章主要給大家介紹了關(guān)于MyBatis-Plus中最簡單的查詢操作的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2022-03-03Spring Boot 訪問安全之認(rèn)證和鑒權(quán)詳解
這篇文章主要介紹了Spring Boot 訪問安全之認(rèn)證和鑒權(quán),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11SpringBoot + SpringSecurity 環(huán)境搭建的步驟
這篇文章主要介紹了SpringBoot + SpringSecurity 環(huán)境搭建的步驟,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-05-05【Java】BigDecimal實(shí)現(xiàn)加減乘除運(yùn)算代碼
本篇文章主要介紹了【Java】BigDecimal實(shí)現(xiàn)加減乘除運(yùn)算代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-02-02mybatis映射內(nèi)部類的使用及注意事項(xiàng)說明
這篇文章主要介紹了mybatis映射內(nèi)部類的使用及注意事項(xiàng)說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12SpringAOP中的切點(diǎn)表達(dá)式Pointcut詳解
這篇文章主要介紹了SpringAOP中的切點(diǎn)表達(dá)式Pointcut詳解,Spring?的?AOP?中的一個(gè)核心概念是切點(diǎn)(Pointcut),切點(diǎn)表達(dá)式定義通知(Advice)執(zhí)行的范圍,需要的朋友可以參考下2023-08-08Spring Boot 中嵌入式 Servlet 容器自動(dòng)配置原理解析
這篇文章主要介紹了Spring Boot 中嵌入式 Servlet 容器自動(dòng)配置原理解析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11