All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.apexes.commons.lang.Strings Maven / Gradle / Ivy

There is a newer version: 2.1.6
Show newest version
/*
 * Copyright (c) 2018, apexes.net. All rights reserved.
 *
 *         http://www.apexes.net
 *
 */
package net.apexes.commons.lang;

import java.text.MessageFormat;
import java.util.Collection;
import java.util.Random;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 
 * @author HeDYn
 *
 */
public final class Strings {
    private Strings() {}

    private static final Random random = new Random();

    public static String[] shorts(String src) {
        String hex = Bytes.toHex(Secrets.md5(src));
        String[] arr = new String[4];
        for (int i = 0; i < 4; i++) {
            // 把hex按照8位一组16进制与0x3FFFFFFF 进行位与运算
            String sub = hex.substring(i * 8, i * 8 + 8);
            // 这里需要使用long型来转换,因为Inteper.parseInt()只能处理31位, 首位为符号位, 如果不用long,则会越界
            long hexLong = 0x3FFFFFFF & Long.parseLong(sub, 16);
            StringBuilder outChars = new StringBuilder();
            for (int j = 0; j < 6; j++) {
                // 把得到的值与0x0000003D进行位与运算,取得字符数组chars索引
                long index = 0x0000003D & hexLong;
                // 把取得的字符相加
                outChars.append(Radix62.ALPHABET[(int) index]);
                // 每次循环按位右移5位
                hexLong = hexLong >> 5;
            }
            // 把字符串存入对应索引的输出数组
            arr[i] = outChars.toString();
        }
        return arr;
    }

    public static String hash(String src) {
        StringBuilder sb = new StringBuilder();
        int hash = Math.abs(MurmurHash.hash32(src));
        while (hash > 0) {
            int index = hash % Radix62.ALPHABET.length;
            hash = hash / Radix62.ALPHABET.length;
            sb.insert(0, Radix62.ALPHABET[index]);
        }
        return sb.toString();
    }
    
    /**
     * 返回一个定长的随机字符串(只包含大小写字母、数字)
     * @param length 随机字符串长度
     * @return 随机字符串
     */
    public static String randomString(int length) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            sb.append(Radix62.ALPHABET[random.nextInt(Radix62.ALPHABET.length)]);
        }
        return sb.toString();
    }
    
    /**
     * 返回一个定长的随机纯字母字符串(只包含大小写字母)
     * @param length 随机字符串长度
     * @return 随机字符串
     */
    public static String randomLetter(int length) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            sb.append(Radix62.ALPHABET[10 + random.nextInt(Radix62.ALPHABET.length - 10)]);
        }
        return sb.toString();
    }

    /**
     * 生成一个定长的随机纯数字字符串
     * @param length 随机字符串长度
     * @return 随机字符串
     */
    public static String randomNumber(int length) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            sb.append(random.nextInt(10));
        }
        return sb.toString();
    }

    private static final char[] UNALIKE_CHARACTER_SET = "23456789ABDEFGHJLMNQRTYabdefghijmnqrty".toCharArray();

    /**
     * 生成一个容易辨认字符组成的定长随机字符串
     * @param length 随机字符串长度
     * @return 随机字符串
     */
    public static String randomUnalikeString(int length) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            sb.append(UNALIKE_CHARACTER_SET[random.nextInt(UNALIKE_CHARACTER_SET.length)]);
        }
        return sb.toString();
    }
    
    /**
     * 去除字符串前面空白
     * @param str 字符串
     * @return 返回去除字符串前面空白后的字符串
     */
    public static String ltrim(String str) {
        int len = str.length();
        int st = 0;
        char[] val = str.toCharArray();
        
        while ((st < len) && (val[st] <= ' ')) {
            st++;
        }
        return (st > 0) ? str.substring(st, len) : str;
    }
    
    /**
     * 去除字符串后面空白
     * @param str 字符串
     * @return 返回去除字符串后面空白后的字符串
     */
    public static String rtrim(String str) {
        int len = str.length();
        char[] val = str.toCharArray();
        
        while ((0 < len) && (val[len - 1] <= ' ')) {
            len--;
        }
        return (len < str.length()) ? str.substring(0, len) : str;
    }
    
    /**
     * 将首字节大写。注意:此方法与JavaBean规范中定义的属性的getter、setter方法名称不同。
     * @param str 字符串
     * @return 返回首字节大写后的字符串
     */
    public static String capitalize(String str) {
        if (str == null || str.isEmpty()) {
            return str;
        }
        return Character.toTitleCase(str.charAt(0)) + str.substring(1);
    }
    
    /**
     * 将首字节小写。注意:此方法与JavaBean规范中定义的属性的getter、setter方法名称不同。
     * @param str 字符串
     * @return 返回首字节小写后的字符串
     */
    public static String uncapitalized(String str) {
        if (str == null || str.isEmpty()) {
            return str;
        }
        return Character.toLowerCase(str.charAt(0)) + str.substring(1);
    }

    /**
     * @deprecated 使用 {@link #uncapitalized(String)}
     */
    @Deprecated
    public static String uncapitalize(String str) {
        return uncapitalized(str);
    }
    
    /**
     * 将驼峰式字符串转换为下划线小写方式。如果转换前的字符串为空,则返回空字符串。
* 转换规格是:在大写字符前增加“_”并转为小写 * 例如:helloWorld->hello_world * @param str 转换前的驼峰式字符串 * @return 转换后下划线方式字符串 */ public static String underscore(String str) { if (str == null || str.trim().isEmpty()) { return ""; } int len = str.length(); StringBuilder sb = new StringBuilder(len); for (int i = 0; i < len; i++) { char ch = str.charAt(i); if (Character.isUpperCase(ch)) { sb.append("_"); sb.append(Character.toLowerCase(ch)); } else { sb.append(ch); } } return sb.toString(); } /** * 将下划线方式字符串转为小驼峰式。如果转换前的字符串为空,则返回空字符串。
* 转换规格是:去掉“_”并大写其后的一个字符 * 例如:hello_world->helloWorld * @param str 转换前的下划线方式字符串 * @return 转换后小驼峰式命名字符串 */ public static String camelCase(String str) { if (str == null || str.trim().isEmpty()) { return ""; } int len = str.length(); StringBuilder sb = new StringBuilder(len); for (int i = 0; i < len; i++) { char ch = str.charAt(i); if (ch == '_') { i++; if (i >= len) { sb.append(ch); break; } sb.append(Character.toUpperCase(str.charAt(i))); } else { sb.append(ch); } } return sb.toString(); } /** * 使用 fmt 做模板格式化给定的参数,作用与 {@link MessageFormat#format(String, Object...)} 相同 * @param fmt 模板 * @param params 参数 * @return 返回格式化后的字符串 */ public static String format(String fmt, final Object... params) { if (params != null && params.length > 0) { // MessageFormat 要求 It's 中的 ' 是 '' String pattern = fmt.replaceAll("'", "''"); return MessageFormat.format(pattern, params); } return fmt; } /** * 将数组转为用指定分隔符分隔的字符串 * @param array 数据 * @param separator 分隔符 * @return 返回用指定分隔符分隔的字符串 */ public static String toString(Object[] array, String separator) { StringBuilder sb = new StringBuilder(); for (Object object : array) { if (sb.length() > 0) { sb.append(separator); } sb.append(object); } return sb.toString(); } /** * 按指定长度,省略字符串部分字符 * * @param str 字符串 * @param length 保留字符串字数 * * @return 省略后的字符串 */ public static String omitString(String str, int length) { if (str == null) { return null; } if (length <= 0) { return ""; } if (str.length() <= length) { return str; } StringBuilder buf1 = new StringBuilder(); StringBuilder buf2 = new StringBuilder(); int i1 = 0; int i2 = str.length() - 1; char c; length -= 3; while (length > 0) { c = str.charAt(i1); length--; buf1.append(c); i1++; if (length > 0 ) { c = str.charAt(i2); length--; buf2.insert(0, c); i2--; } } buf1.append("..."); buf1.append(buf2); return buf1.toString(); } /** * 如果指定字符串长度超过了最大长度,则对指定的字符串做截断处理 * @param text 字符串 * @param maxLength 最大长度 * @return 返回长度不超过 maxLength 的字段串 */ public static String truncation(String text, int maxLength) { if (text != null && text.length() > maxLength) { return text.substring(0, maxLength); } return text; } /** * Returns a string, of length at least {@code minLength}, consisting of {@code string} prepended * with as many copies of {@code padChar} as are necessary to reach that length. For example, * *
    *
  • {@code padStart("7", 3, '0')} returns {@code "007"} *
  • {@code padStart("2010", 3, '0')} returns {@code "2010"} *
* *

See {@link java.util.Formatter} for a richer set of formatting capabilities. * * @param string the string which should appear at the end of the result * @param minLength the minimum length the resulting string must have. Can be zero or negative, in * which case the input string is always returned. * @param padChar the character to insert at the beginning of the result until the minimum length * is reached * @return the padded string */ public static String padStart(String string, int minLength, char padChar) { Checks.verifyNotNull(string, "string"); if (string.length() >= minLength) { return string; } StringBuilder sb = new StringBuilder(minLength); for (int i = string.length(); i < minLength; i++) { sb.append(padChar); } sb.append(string); return sb.toString(); } /** * Returns a string, of length at least {@code minLength}, consisting of {@code string} appended * with as many copies of {@code padChar} as are necessary to reach that length. For example, * *

    *
  • {@code padEnd("4.", 5, '0')} returns {@code "4.000"} *
  • {@code padEnd("2010", 3, '!')} returns {@code "2010"} *
* *

See {@link java.util.Formatter} for a richer set of formatting capabilities. * * @param string the string which should appear at the beginning of the result * @param minLength the minimum length the resulting string must have. Can be zero or negative, in * which case the input string is always returned. * @param padChar the character to append to the end of the result until the minimum length is * reached * @return the padded string */ public static String padEnd(String string, int minLength, char padChar) { Checks.verifyNotNull(string, "string"); if (string.length() >= minLength) { return string; } StringBuilder sb = new StringBuilder(minLength); sb.append(string); for (int i = string.length(); i < minLength; i++) { sb.append(padChar); } return sb.toString(); } /** * Returns a string consisting of a specific number of concatenated copies of an input string. For * example, {@code repeat("hey", 3)} returns the string {@code "heyheyhey"}. * *

Java 11+ users: use {@code string.repeat(count)} instead. * * @param string any non-null string * @param count the number of times to repeat it; a nonnegative integer * @return a string containing {@code string} repeated {@code count} times (the empty string if * {@code count} is zero) * @throws IllegalArgumentException if {@code count} is negative */ public static String repeat(String string, int count) { Checks.verifyNotNull(string, "string"); if (count <= 1) { return (count == 0) ? "" : string; } final int len = string.length(); final long longSize = (long) len * (long) count; final int size = (int) longSize; if (size != longSize) { throw new ArrayIndexOutOfBoundsException("Required array size too large: " + longSize); } final char[] array = new char[size]; string.getChars(0, len, array, 0); int n; for (n = len; n < size - n; n <<= 1) { System.arraycopy(array, 0, array, n, n); } System.arraycopy(array, 0, array, n, size - n); return new String(array); } public static String nullToEmpty(String string) { return string == null ? "" : string; } public static String emptyToNull(String string) { return string == null || string.isEmpty() ? null : string; } /** * 将容器中的元素以 separator 分隔进行拼接 * @param collection 要拼接的数据 * @param separator 分隔符 * @return 返回拼接后的字符串 */ public static String join(Collection collection, String separator) { return join(collection.toArray(), separator); } /** * 将容器中的元素以 separator 分隔进行拼接 * @param array 要拼接的数据 * @param separator 分隔符 * @return 返回拼接后的字符串 */ public static String join(Object[] array, String separator) { if (array == null || array.length == 0) { return null; } StringBuilder sb = new StringBuilder(); sb.append(array[0]); for (int i = 1; i < array.length; i++) { sb.append(separator).append(array[i]); } return sb.toString(); } /** * 解码 unicode 编码字符串 * @param unicode unicode编码的字符串 * @return 返回解码后的字符串 */ public static String fromUnicode(String unicode) { Pattern pattern = Pattern.compile("(\\\\u(\\p{XDigit}{4}))"); Matcher matcher = pattern.matcher(unicode); char ch; while (matcher.find()) { ch = (char) Integer.parseInt(matcher.group(2), 16); unicode = unicode.replace(matcher.group(1), ch + ""); } return unicode; } /** * 转为 unicode 编码字符串 * @param input 要编码的字符串 * @return 返回编码后的字符串 */ public static String toUnicode(String input) { StringBuilder builder = new StringBuilder(); for (char ch : input.toCharArray()) { builder.append(String.format("\\u%04x", (int) ch)); } return builder.toString(); } /** * 将指定的字符串转换成适合HTML格式的字符串。 */ public static String stringToHTMLString(String text) { StringBuilder sb = new StringBuilder(text.length()); // true if last char was blank boolean lastWasBlankChar = false; int len = text.length(); char c; for (int i = 0; i < len; i++) { c = text.charAt(i); if (c == ' ') { // blank gets extra work, // this solves the problem you get if you replace all // blanks with  , if you do that you loss // word breaking if (lastWasBlankChar) { lastWasBlankChar = false; sb.append(" "); } else { lastWasBlankChar = true; sb.append(' '); } } else { lastWasBlankChar = false; // // HTML Special Chars if (c == '"') { sb.append("""); } else if (c == '&') { sb.append("&"); } else if (c == '<') { sb.append("<"); } else if (c == '>') { sb.append(">"); } else if (c == '\n') { // Handle Newline sb.append("<br/>"); } else { int ci = 0xffff & c; if (ci < 160) { // nothing special only 7 Bit sb.append(c); } else { // Not 7 Bit use the unicode system sb.append("&#"); sb.append(ci); sb.append(';'); } } } } return sb.toString(); } /** * 获取自增型文件名。 * 如: * a.txt --> a_1.txt * b_5.txt --> b_6.txt * c_2 --> c_3 */ public static String autoincrementFilename(String filename) { String s1; String s2; String suffix; String tmp; int m = filename.lastIndexOf('.'); if (m >= 0) { tmp = filename.substring(0, m); suffix = filename.substring(m); } else { tmp = filename; suffix = ""; } int n = tmp.lastIndexOf('_'); if (n >= 0) { s1 = tmp.substring(0, n); s2 = tmp.substring(n+1); } else { s1 = tmp; s2 = ""; } int i = 1; if (s2.matches("^[1-9]\\d*$")) { try { i = Integer.parseInt(s2); } catch (Exception ex) { // ignore } i++; return s1 + "_" + i + suffix; } if (m != -1) { return tmp + "_"+ i + suffix; } return filename + "_"+ i; } /** * 比较version1和version2,如果version1小于、等于、大于version2分别返回 -1、0、1 * @param version1 版本号1 * @param version2 版本号2 * @return 比较version1和version2,如果version1小于、等于、大于version2分别返回 -1、0、1 */ public static int versionCompare(String version1, String version2) { if (Checks.isBlank(version1)) { return Checks.isBlank(version2) ? 0 : -1; } else if (Checks.isBlank(version2)) { return 1; } StringTokenizer t1 = new StringTokenizer(version1, "._"); StringTokenizer t2 = new StringTokenizer(version2, "._"); while (true) { int n1 = 0; int n2 = 0; int c = 2; if (t1.hasMoreTokens()) { n1 = Integer.parseInt(t1.nextToken()); } else { c--; } if (t2.hasMoreTokens()) { n2 = Integer.parseInt(t2.nextToken()); } else { c--; } if (c == 0) { break; } int d = Integer.compare(n1, n2); if (d != 0) { return d; } } return 0; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy