背景
按长度截取字符功能是为了解决什么问题呢?首先了解下两个维度的基础
1. Java中很多工具类在按长度截取文本的时候,中文/英文/数字/中英文标点符号每一个都代表一个长度,比如subString方法
2. 一个中文和英文数字所占的内存和显示的大小也不同,中文和英文数字宽度不同如下➡️: 宽度 kd
问题
当UI或者功能要求按长宽高等固定尺寸来作为衡量标准的时候,那么长度就不能作为我们的衡量标准,因为1个中文长度是1个单位,1个数字长度也是1个单位,而实际他们所占的尺寸是不同的,那么怎么解决呢?我们就得找一个统一的衡量标准,也就是字符
按字符为单位截取
public class TextUtils {
/**
* 按字符截取长度
*
* @param text 原文本
* @param maxLength 截取长度(按字符)
* @return
*/
public static String subStringByChar(String text, Integer maxLength){
if (StringUtils.isBlank(text)) {
return text;
}
//名称最多展示14个字符,一个汉字算两个字符,超过展示...
StringBuilder sBuilder = new StringBuilder();
char[] chars = text.toCharArray();
int length = 0;
for (char ch : chars){
boolean chineseChar = isChineseChar(ch) || isSymbol(ch);
length = length + (chineseChar ? 2 : 1);
if (length > maxLength){
break;
}
sBuilder.append(ch);
}
String testResult = sBuilder.toString();
if (length > maxLength){
testResult = testResult + "...";
}
return testResult;
}
/**
* 是否汉字字符
* @param c
* @return
*/
private static boolean isChineseChar(char c) {
return String.valueOf(c).matches("[\u4e00-\u9fa5]");
}
/**
* 是否中文符号
* @param ch
* @return
*/
private static boolean isSymbol(char ch)
{
if(isCnSymbol(ch)) return true;
if(isEnSymbol(ch))return true;
if(0x2010 <= ch && ch <= 0x2017) return true;
if(0x2020 <= ch && ch <= 0x2027) return true;
if(0x2B00 <= ch && ch <= 0x2BFF) return true;
if(0xFF03 <= ch && ch <= 0xFF06) return true;
if(0xFF08 <= ch && ch <= 0xFF0B) return true;
if(ch == 0xFF0D || ch == 0xFF0F) return true;
if(0xFF1C <= ch && ch <= 0xFF1E) return true;
if(ch == 0xFF20 || ch == 0xFF65) return true;
if(0xFF3B <= ch && ch <= 0xFF40) return true;
if(0xFF5B <= ch && ch <= 0xFF60) return true;
if(ch == 0xFF62 || ch == 0xFF63) return true;
if(ch == 0x0020 || ch == 0x3000) return true;
return false;
}
private static boolean isCnSymbol(char ch) {
if (0x3004 <= ch && ch <= 0x301C) return true;
if (0x3020 <= ch && ch <= 0x303F) return true;
return false;
}
private static boolean isEnSymbol(char ch){
if (ch == 0x40) return true;
if (ch == 0x2D || ch == 0x2F) return true;
if (0x23 <= ch && ch <= 0x26) return true;
if (0x28 <= ch && ch <= 0x2B) return true;
if (0x3C <= ch && ch <= 0x3E) return true;
if (0x5B <= ch && ch <= 0x60) return true;
if (0x7B <= ch && ch <= 0x7E) return true;
return false;
}
}