package com.jfai.util;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Random;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import lombok.extern.slf4j.Slf4j;
/**
* @author wanglf
* @version 1.6.3
* @Package com.jfai.kg.util
* @Description: StringUtil
* @date 2018年7月1日13:54:26
* @remark
* 新增isNull判断专制各种空值问题 2018年7月13日17:34:45
* 新增获取随机年龄,手机号,身份证号等测试数据功能 2018年8月5日09:47:18
* 集成修复unicode转义字符串功能 2018年8月5日09:56:20
* 新增cumulationOne功能 2018年8月13日17:07:15
* 重构 2018年8月14日18:04:44
* 新增首字母大小写转换方法 2018年8月23日16:31:37
*/
@Slf4j
public class StringUtil {
/**
* 百家姓
*/
public static final String XS = "赵钱孙李周吴郑王冯陈褚卫蒋沈韩杨朱秦尤许何吕施张孔曹严华金魏陶姜戚谢邹喻柏水窦章云苏潘葛奚范彭郎鲁韦昌马苗凤花方俞任袁柳酆鲍史唐费廉岑薛雷贺倪汤滕殷罗毕郝邬安常乐于时傅皮卞齐康伍余元卜顾孟平黄和穆萧尹姚邵湛汪祁毛禹狄米贝明臧计伏成戴谈宋茅庞熊纪舒屈项祝董梁杜阮蓝闵席季麻强贾路娄危江童颜郭梅盛林刁钟徐邱骆高夏蔡田樊胡凌霍虞万支柯昝管卢莫经房裘缪干解应宗丁宣贲邓郁单杭洪包诸左石崔吉钮龚程嵇邢滑裴陆荣翁荀羊於惠甄曲家封芮羿储靳汲邴糜松井段富巫乌焦巴弓牧隗山谷车侯宓蓬全郗班仰秋仲伊宫宁仇栾暴甘钭厉戎祖武符刘景詹束龙叶幸司韶郜黎蓟薄印宿白怀蒲邰从鄂索咸籍赖卓蔺屠蒙池乔阴鬱胥能苍双闻莘党翟谭贡劳逄姬申扶堵冉宰郦雍卻璩桑桂濮牛寿通边扈燕冀郏浦尚农温别庄晏柴瞿阎充慕连茹习宦艾鱼容向古易慎戈廖庾终暨居衡步都耿满弘匡国文寇广禄阙东欧殳沃利蔚越夔隆师巩厍聂晁勾敖融冷訾辛阚那简饶空曾毋沙乜养鞠须丰巢关蒯相查后荆红游竺权逯盖益桓公万俟司马上官欧阳夏侯诸葛闻人东方赫连皇甫尉迟公羊澹台公冶宗政濮阳淳于单于太叔申屠公孙仲孙轩辕令狐钟离宇文长孙慕容鲜于闾丘司徒司空丌官司寇仉督子车颛孙端木巫马公西漆雕乐正壤驷公良拓跋夹谷宰父谷梁晋楚闫法汝鄢涂钦段干百里东郭南门呼延归海羊舌微生岳帅缑亢况郈有琴梁丘左丘东门西门商牟佘佴伯赏南宫墨哈谯笪年爱阳佟";
public static final String BASE = "abcdefghijklmnopqrstuvwxyz0123456789";
public static final String BASE_MIN = "abcdefghijkmnpqrtuvwxyz0123456789";
public static final String BASE_EX = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
public static int[] months = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
private static Random random = new Random();
/**
* 获取简单的中文名字
*/
public static String getSimpleChineseName() {
StringBuilder sb = new StringBuilder();
sb.append(XS.charAt(new Random().nextInt(XS.length()))).append(getRandomChineseChar()).append(getRandomChineseChar());
return sb.toString();
}
/**
* 获取随机年龄,一般用来做测试数据用
*
* @return 随机年龄
* @Attention: 返回的年龄数字在10-99
*/
public static int getRandomAge() {
return Integer.parseInt(getNum(2));
}
/**
* 获取随机生日字符串,返回yyyyMMdd格式的日期字符串
*
* @return 随机的生日字符串, yyyyMMdd格式
* @Attention:返回的年龄区间在1910-2018年之间,暂不包含2018
* @remark:new Random().nextInt(10) 会返回0-9之间的随机整数,包括0或9,但不包括10
*/
public static String getRandomBirthdayString() {
int year = 1910 + random.nextInt(108);
int month = months[random.nextInt(12)];
int day = 1 + random.nextInt(28);
StringBuilder stb = new StringBuilder();
stb.append(year);
if (month < 10) {
stb.append("0").append(month);
} else {
stb.append(month);
}
if (day < 10) {
stb.append("0").append(day);
} else {
stb.append(day);
}
return stb.toString();
}
/**
* 获取随机身份证号,注意该身份证号只是大致看着相似,用来测试用,严格的身份证号校验是通不过的
*
* @return 随机的18位身份证号
* @Attention:严格的身份证号校验是通不过的
*/
public static String getRandomIDNo() {
// RegUtil 如不想引用 可以用随机的两位数字替代前两位
Object[] array = RegUtil.GetAreaCode().keySet().toArray();
String areacode = (String) array[random.nextInt(array.length)];
StringBuilder stb = new StringBuilder(areacode);
stb.append(getNum(4)).append(getRandomBirthdayString()).append(getNum(4));
return stb.toString();
}
/**
* 获取随机手机号,注意有可能在在严格的手机号验证中通不过
*
* @return 随机手机号
*/
public static String getRandomMobileNumber() {
StringBuilder stb = new StringBuilder();
stb.append(1).append(3 + random.nextInt(7)).append(getNum(9));
return stb.toString();
}
/**
* 获取一段指定长度首字母不为0的随机数字
*
* @param count 要获取的随机数字的位数
* @return 随机数字组成的字符串
* @Attention 首字母时
*/
public static String getRandomNumber(int count) {
return getNum(count);
}
public static String getRandomStr(int length) {
if (length <= 0) {
return "";
}
int randomNum;
char randomChar;
// StringBuffer类型的可以append增加字符
StringBuffer stb = new StringBuffer();
for (int i = 0; i < length; i++) {
// 可生成[0,n)之间的整数,获得随机位置
randomNum = random.nextInt(BASE_MIN.length());
// 获得随机位置对应的字符
randomChar = BASE_MIN.charAt(randomNum);
// 组成一个随机字符串
stb.append(randomChar);
}
return stb.toString();
}
/**
* @return 单个常见汉字字符
* @Description: 随机生成单个常见汉字
*/
public static String getRandomChineseChar() {
String str = "";
int highCode;
int lowCode;
Random random = new Random();
highCode = (176 + Math.abs(random.nextInt(39))); // B0 + 0~39(16~55) 一级汉字所占区
lowCode = (161 + Math.abs(random.nextInt(93))); // A1 + 0~93 每区有94个汉字
byte[] b = new byte[2];
b[0] = (Integer.valueOf(highCode)).byteValue();
b[1] = (Integer.valueOf(lowCode)).byteValue();
try {
str = new String(b, "GBK");
} catch (Exception e) {
log.error("Exception :", e);
}
return str;
}
/**
* 获取一段指定长度首字母不为0的随机数字
*
* @param count 要获取的随机数字的位数
* @return 随机数字组成的字符串
*/
public static String getNum(int count) {
if (count <= 0) {
return "";
}
StringBuilder s = new StringBuilder();
for (int i = 0; i < count; i++) {
s.append(new Random().nextInt(10));
}
String string = s.toString();
// 如果第一位数字为0,则替换为1
return string.charAt(0) == '0' ? "1" + string.substring(1) : string;
}
/**
* 获取UUID
*/
public static String getUUID() {
return UUID.randomUUID().toString();
}
/**
* 字符串替换,将 source 中的 oldString 全部换成 newString
*
* @param source 源字符串
* @param oldString 老的字符串
* @param newString 新的字符串
* @return 替换后的字符串
* @Description 主要用于输入的表单字符串转化成HTML格式的文本
*/
public static String Replace(String source, String oldString, String newString) {
StringBuffer output = new StringBuffer();
int lengthOfSource = source.length(); // 源字符串长度
int lengthOfOld = oldString.length(); // 老字符串长度
int posStart = 0; // 开始搜索位置
int pos; // 搜索到老字符串的位置
while ((pos = source.indexOf(oldString, posStart)) >= 0) {
output.append(source.substring(posStart, pos));
output.append(newString);
posStart = pos + lengthOfOld;
}
if (posStart < lengthOfSource) {
output.append(source.substring(posStart));
}
return output.toString();
}
/**
* 将传入的字符串形式的数字,累加1后以字符串的形式返回
*
* @param num
* @return 累加1后的字符串
* @version 1.0.0
* @Attention 传入的必须是数字
*/
public static String cumulationOne(String num) {
long parseLong = Long.parseLong(num);
return String.valueOf((parseLong + 1));
}
/**
* @param key String
* @param value String
* @return HashMap<String, String>
*/
public static Map <String, String> toMap(String key, String value) {
Map <String, String> map = new LinkedHashMap <String, String>();
map.put(key, value);
return map;
}
/**
* @param key String
* @param value Object
* @return Map<String, Object>
*/
public static Map <String, Object> toMap(String key, Object value) {
Map <String, Object> map = new LinkedHashMap <String, Object>();
map.put(key, value);
return map;
}
/**
* 判断字符串是否为int类型数据
*
* @param str
* @return boolean
*/
public static boolean isInt(String str) {
try {
Integer.parseInt(str);
return true;
} catch (Exception e) {
return false;
}
}
/**
* 判断字符串是否为long类型数据
*
* @param str
* @return boolean
*/
public static boolean isLong(String str) {
try {
Long.parseLong(str);
return true;
} catch (Exception e) {
return false;
}
}
/**
* 判断字符是否为空
*/
public static boolean isEmpty(String str) {
return str == null || str.length() == 0;
}
/**
* 判断字符是否为不为空
*/
public static boolean isNotEmpty(String str) {
return !isEmpty(str);
}
/**
* 判断字符是否为空或空白字符串或null组成
*/
public static boolean isBlank(String str) {
return str == null || str.length() == 0 || str.trim().equals("");
}
/**
* 判断字符是否为不为空或空白字符串组成
*/
public static boolean isNotBlank(String str) {
return !isBlank(str);
}
/**
* 判断字符是否为空或空白字符串,或各种null组成
*/
public static boolean isNull(String str) {
return str == null || str.length() == 0 || "".equals(str.trim()) || "NULL".equals(str.trim().toUpperCase());
}
/**
* 判断字符是否为不为空或空白字符串,或各种null组成
*/
public static boolean isNotNull(String str) {
return !isNull(str);
}
/**
* 判断字符串是否可用 [isNotNull功能的升级版]
*/
public static boolean isAvailable(String str) {
return !(str == null || str.length() == 0 || "".equals(str.trim()) || "NULL".equals(str.trim().toUpperCase()) || "NULLNULL".equals(str.trim().toUpperCase()) || "NULLNULLNULL".equals(str.trim().toUpperCase()));
}
/**
* 核查字符长度
*/
public static boolean checkLength(String str, int minlen, int maxlen) {
int len = 0;
if (str != null) {
len = str.length();
}
if (len >= minlen && len <= maxlen) {
return true;
} else {
return false;
}
}
/**
* @param str
* @Description: 判断字符串是否是UUID字符串
*/
public static boolean isUUID(String str) {
try {
UUID.fromString(str);
return true;
} catch (Exception e) {
return false;
}
}
/**
* 首字母转小写
*/
public static String toLowerCaseFirstOne(String s) {
if (Character.isLowerCase(s.charAt(0)))
return s;
else
return (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString();
}
/**
* 首字母转大写
*/
public static String toUpperCaseFirstOne(String s) {
if (Character.isUpperCase(s.charAt(0)))
return s;
else
return (new StringBuilder()).append(Character.toUpperCase(s.charAt(0))).append(s.substring(1)).toString();
}
/**
* 依据start(开始位置)和end(结束位置)截取目标字符串,包含start和end位置
*
* @param start 截取的开始位置 注:是自然位置不是下标
* @param end 结束位置,自然位置不是下标
* @param str 目标字符串
* @return 截取的目标字符串
* @version 1.0.0
* @Attention 参数start和end都是自然位置, 注意自然位置不包括0, 最大长度就是字符串长度..
* start如果小于等于0,会自动调整到开始位置,end如果超出源字符串最大长度,则自动调整为源字符串结束位置
*/
public static String getStr(int start, int end, String str) {
if (start <= 0) {
start = 1;
}
if (end > str.length()) {
end = str.length();
}
return str.substring(start - 1, end);
}
/**
* 修改字符串中的unicode码,将unicode编码转换成原来的字符
*
* @param s 源str
* @return 修改后的str
*/
private static String decode(String s) {
StringBuilder sb = new StringBuilder(s.length());
char[] chars = s.toCharArray();
for (int i = 0; i < chars.length; i++) {
char c = chars[i];
if (c == '\\' && chars[i + 1] == 'u') {
char cc = 0;
for (int j = 0; j < 4; j++) {
char ch = Character.toLowerCase(chars[i + 2 + j]);
if ('0' <= ch && ch <= '9' || 'a' <= ch && ch <= 'f') {
cc |= (Character.digit(ch, 16) << (3 - j) * 4);
} else {
cc = 0;
break;
}
}
if (cc > 0) {
i += 5;
sb.append(cc);
continue;
}
}
sb.append(c);
}
return sb.toString();
}
/**
* 获取修复unicode转义后的字符串 如 将字符串中的 "\u003d" 转回其原本的值
*
* @param str
* @return 修复后的字符串
*/
public static String getFixStrBecauseUnicodeEscape(String str) {
Pattern p = Pattern.compile("(\\\\u.{4})");
Matcher m = p.matcher(str);
while (m.find()) {
String xxx = m.group();
str = str.replaceAll("\\" + xxx, decode(xxx));
}
return str;
}
}