使用Java打印字符串表格(中英文内容不乱)

最近在学习使用java来编写cli应用,但是在信息展示上碰到了难题。原因是没有很好工具来展示一个由字符串组成的表格。在git上搜到阿里巴巴有一个叫做 text-ui 的开源项目可以用,但是这个工具在制作表格的时候如果表格内容是中英文混合的,表格就会乱掉。于是就自己写了一个工具类来打印一个字符串组成的表格。
这个工具满足一下使用要求:
- 可以设置标题
- 可以设置表格中数据的左右边距
- 可以设置表格由什么符号组成
- 可以设置表格数据最大长度
代码如下:
package com.hebaibai.ascmd.text; import org.apache.commons.lang3.StringUtils; import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern; public class TextForm { /**
* 左边距
*/
protected int paddingL = 1; /**
* 右边距
*/
protected int paddingR = 1; /**
* 标题
*/
protected List<String> title = new ArrayList<>(); /**
* 数据
*/
protected List<List<String>> datas = new ArrayList<>(); /**
* 最大列数
*/
protected int maxCol = 0; /**
* 每个单元格最大字符数
*/
protected int colMaxLength = 8; /**
* 表格组成符号
*/
protected char separator = '.'; private TextForm() {
} public static TextFormBulider bulider() {
return new TextFormBulider(new TextForm());
} /**
* 格式化输出表格
*/
public void printFormat() {
List<List<String>> formData = new ArrayList<>();
formData.add(title);
formData.addAll(datas);
Map<Integer, Integer> colMaxLengthMap = colMaxLength(formData);
for (int i = 0; i < formData.size(); i++) {
List<String> row = formData.get(i);
for (int j = 0; j < row.size(); j++) {
Formatter formatter = new Formatter();
String str = row.get(j);
if (str.length() > colMaxLength) {
str = str.substring(0, colMaxLength);
}
int chineseNum = getChineseNum(str);
Integer maxLength = colMaxLengthMap.get(j);
String val = formatter.format("%-" + (maxLength - chineseNum) + "s", str).toString();
row.set(j, val);
}
}
Map<Integer, Integer> colMinBlankLengthMap = colMinBlankLength(formData);
for (int i = 0; i < formData.size(); i++) {
List<String> row = formData.get(i);
for (int j = 0; j < row.size(); j++) {
String val = row.get(j);
Integer minBlankLength = colMinBlankLengthMap.get(j);
val = val.substring(0, val.length() - minBlankLength);
row.set(j, val);
}
}
String line = "";
List<String> rows = new ArrayList<>();
for (List<String> strings : formData) {
String pL = StringUtils.repeat(" ", paddingL);
String pR = StringUtils.repeat(" ", paddingR);
String row = separator + pL + String.join(pL + separator + pR, strings) + pR + separator;
if (line.length() < row.length()) {
line = StringUtils.repeat(separator, row.length());
}
rows.add(row);
}
System.out.println(line);
for (String row : rows) {
System.out.println(row);
System.out.println(line);
}
} /**
* 找到每一列最大的长度
*
* @param formData
* @return
*/
private Map<Integer, Integer> colMaxLength(List<List<String>> formData) {
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < formData.size(); i++) {
int col = 0;
List<String> strings = formData.get(i);
while (strings.size() > col) {
String val = strings.get(col);
if (val.length() > colMaxLength) {
val = val.substring(0, colMaxLength);
strings.set(col, val);
}
int length = val.getBytes().length;
Integer integer = map.get(col);
if (integer == null) {
map.put(col, length);
} else {
if (integer < length) {
map.put(col, length);
}
}
col++;
}
}
return map;
} /**
* 找到每一列从右开始最小的空格长度
*
* @param formData
* @return
*/
private Map<Integer, Integer> colMinBlankLength(List<List<String>> formData) {
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < formData.size(); i++) {
int col = 0;
List<String> strings = formData.get(i);
while (strings.size() > col) {
String val = strings.get(col);
int length = 0;
for (int i1 = val.length() - 1; i1 >= 0; i1--) {
if (val.charAt(i1) == ' ') {
length++;
} else {
break;
}
}
Integer integer = map.get(col);
if (integer == null) {
map.put(col, length);
} else {
if (integer > length) {
map.put(col, length);
}
}
col++;
}
}
return map;
} /**
* 获取中文数量
*
* @param val
* @return
*/
private int getChineseNum(String val) {
if (val == null) {
val = "null";
}
String regex = "[\u4e00-\u9fa5|。|,]";
ArrayList<String> list = new ArrayList<String>();
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(val);
while (matcher.find()) {
list.add(matcher.group());
}
int size = list.size();
return size;
}
}
package com.hebaibai.ascmd.text; import java.util.ArrayList;
import java.util.List; public class TextFormBulider {
private TextForm textForm; protected TextFormBulider(TextForm textForm) {
this.textForm = textForm;
} public TextFormBulider title(String... titles) {
if (textForm.maxCol < titles.length) {
textForm.maxCol = titles.length;
}
for (String title : titles) {
if (title == null) {
title = "null";
}
textForm.title.add(title);
}
return this;
} public TextFormBulider paddingL(int paddingL) {
textForm.paddingL = paddingL;
return this;
} public TextFormBulider paddingR(int paddingR) {
textForm.paddingR = paddingR;
return this;
} public TextFormBulider separator(char separator) {
textForm.separator = separator;
return this;
} public TextFormBulider colMaxLength(int colMaxLength) {
textForm.colMaxLength = colMaxLength;
return this;
} public TextFormBulider addRow(String... cols) {
if (textForm.maxCol < cols.length) {
textForm.maxCol = cols.length;
}
List<String> list = new ArrayList<>(cols.length);
for (String col : cols) {
if (col == null) {
col = "null";
}
list.add(col);
}
textForm.datas.add(list);
return this;
} public TextForm finish() {
int titleSize = textForm.title.size();
if (titleSize < textForm.maxCol) {
for (int i = 0; i < textForm.maxCol - titleSize; i++) {
textForm.title.add(null);
}
}
for (List<String> data : textForm.datas) {
int dataSize = data.size();
if (dataSize < textForm.maxCol) {
for (int i = 0; i < textForm.maxCol - dataSize; i++) {
data.add(null);
}
}
}
return textForm;
}
}
使用例子:
@Test
public void printFormat() {
TextForm.bulider()
.title("name", "age", "sex")//设置标题
.addRow("王麻345子", "21", "男2")//添加行
.addRow("wzeefgrerhei", "21", "男")//添加行
.colMaxLength(5)//设置单元格最大数据长度
.separator('*')//设置表格由什么符号构成
.paddingR(2)//右边距
.paddingL(2)//左边距
.finish()//完成
.printFormat();//打印
}
输出结果:
*****************************
* name * age * sex *
*****************************
* 王麻345 * 21 * 男2 *
*****************************
* wzeef * 21 * 男 *
*****************************
原文地址:https://www.cnblogs.com/hebaibai/p/10710491.html
个人站地址:https://www.hebaibai.com/?p=371
使用Java打印字符串表格(中英文内容不乱)的更多相关文章
- 描述了say_hello函数的具体内容,调用zend_printf系统函数在php中打印字符串
下载一个php的源代码包,这里使用的是php 4.0.5版,解压后会看到php的根目录下会有README.EXT_SKEL这样一个文件,打开详细阅读了一下,发现了一个非常好用的工具,这个工具可以帮你构 ...
- python 打印 str 字符串的实际内容 repr(str)
python 打印 str 字符串的实际内容 repr(str) s = 'aa' print(repr(s))
- java判断字符串内容
java判断字符串是否全为数字 String str = "032";boolean isNum = str.matches("[0-9]+"); java判断 ...
- Java打印
Java打印 import java.awt.Color; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Gra ...
- Java之字符串String,StringBuffer,StringBuilder
String类: String类即字符串类型,并不是Java的基本数据类型,但可以像基本数据类型一样使用,用双引号括起来进行声明.在Java中用String类的构造方法来创建字符串变量. 声明字符串: ...
- Java 打印程序设计实例
3.1 打印文本 3.1.1 应用场景 假设我们需要打印一个窗体的某个文本编辑域(可能只有几行,也可能包含多页)的内容,并且每页最多打印 54 行,如何实现呢? 3.1.2 解决方法 基本思路如下:首 ...
- Java基础-字符串(String)常用方法
Java基础-字符串(String)常用方法 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.java的API概念 Java的API(API:Application(应用) Pr ...
- 《Java程序设计》课堂实践内容总结
<Java程序设计>课堂实践内容总结 实践一 要求 修改教材P98 Score2.java, 让执行结果数组填充是自己的学号: 提交在IDEA或命令行中运行结查截图,加上学号水印,没学号的 ...
- 20145209 2016-2017-2 《Java程序设计》课堂实践内容
20145209 2016-2017-2 <Java程序设计>课堂实践内容 一.递归 题目详情: public class TestArgs{ public static void mai ...
随机推荐
- Clion pycharm激活码(可使用到2019年2月)
D87IQPUU3Q-eyJsaWNlbnNlSWQiOiJEODdJUVBVVTNRIiwibGljZW5zZWVOYW1lIjoiTnNzIEltIiwiYXNzaWduZWVOYW1lIjoiI ...
- 小程序json字符串转为对象
小程序里json字符串转为对象使用JSON.parse()方法转变无效, 看报错提示有单引号“ ' ” 因为单引号而无效, 将单引号全改双引号即可. 报错如下: VM11050:1 thirdScri ...
- 使用Linux自带日志滚动工具logrotate滚动redis日志示例
截至到redis-5.0版本,redis仍然不会自动滚动日志文件,如果不处理则日志文件日积月累越来越大,最终将导致磁盘满告警: # ls -lh total 12G -rw-r--r-- 1 redi ...
- Vuejs——(6)Vuejs与form元素
版权声明:出处http://blog.csdn.net/qq20004604 目录(?)[+] 资料来于官方文档: http://cn.vuejs.org/guide/forms.html 本 ...
- Python之旅Day2 元组 字符串 字典 集合
元组(tuple) 元组其实跟列表差不多,也是存一组数,与列表相比,元组一旦创建,便不能再修改,所以又叫只读列表. 语法: names = ("Wuchunwei","Y ...
- XE下显示托盘图标(TrayIcon)
https://www.cnblogs.com/studypanp/p/4930619.html XE下显示托盘图标(TrayIcon) 1.拖一个TrayIcon控件 2.拖一个Applicat ...
- NET Core微服务之路:自己动手实现Rpc服务框架,基于DotEasy.Rpc服务框架的介绍和集成
本篇内容属于非实用性(拿来即用)介绍,如对框架设计没兴趣的朋友,请略过. 快一个月没有写博文了,最近忙着两件事; 一:阅读刘墉先生的<说话的魅力>,以一种微妙的,你我大家都会经常遇见 ...
- Programming Specification
1. Define variable return_code to record the function's status. int return_code = 0; 2. Define the e ...
- 【接口时序】5、QSPI Flash的原理与QSPI时序的Verilog实现
一. 软件平台与硬件平台 软件平台: 1.操作系统:Windows-8.1 2.开发套件:ISE14.7 3.仿真工具:ModelSim-10.4-SE 4.Matlab版本:Matlab2014b/ ...
- 使用 Navicate 连接 Oracle9i 数据库
Navicat Premium 是一个可多重连接的数据库管理工具,它可让你以单一程序同時连接到 MySQL.SQLite.Oracle 及 PostgreSQL 数据库,让管理不同类型的数据库更加方便 ...