mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-07-21 15:09:48 +08:00
add methods
This commit is contained in:
@@ -3,6 +3,9 @@ package cn.hutool.core.codec;
|
||||
import cn.hutool.core.exceptions.UtilException;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.text.StrUtil;
|
||||
import cn.hutool.core.util.CharUtil;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Punycode是一个根据RFC 3492标准而制定的编码系统,主要用于把域名从地方语言所采用的Unicode编码转换成为可用于DNS系统的编码
|
||||
@@ -24,6 +27,27 @@ public class PunyCode {
|
||||
|
||||
public static final String PUNY_CODE_PREFIX = "xn--";
|
||||
|
||||
/**
|
||||
* 将域名编码为PunyCode,会忽略"."的编码
|
||||
*
|
||||
* @param domain 域名
|
||||
* @return 编码后的域名
|
||||
* @throws UtilException 计算异常
|
||||
*/
|
||||
public static String encodeDomain(final String domain) throws UtilException {
|
||||
Assert.notNull(domain, "domain must not be null!");
|
||||
final List<String> split = StrUtil.split(domain, CharUtil.DOT);
|
||||
final StringBuilder result = new StringBuilder(domain.length() * 4);
|
||||
for (final String str : split) {
|
||||
if (result.length() != 0) {
|
||||
result.append(CharUtil.DOT);
|
||||
}
|
||||
result.append(encode(str, true));
|
||||
}
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将内容编码为PunyCode
|
||||
*
|
||||
@@ -48,9 +72,9 @@ public class PunyCode {
|
||||
int n = INITIAL_N;
|
||||
int delta = 0;
|
||||
int bias = INITIAL_BIAS;
|
||||
final StringBuilder output = new StringBuilder();
|
||||
// Copy all basic code points to the output
|
||||
final int length = input.length();
|
||||
final StringBuilder output = new StringBuilder(length * 4);
|
||||
// Copy all basic code points to the output
|
||||
int b = 0;
|
||||
for (int i = 0; i < length; i++) {
|
||||
final char c = input.charAt(i);
|
||||
@@ -119,6 +143,27 @@ public class PunyCode {
|
||||
return output.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 解码 PunyCode为域名
|
||||
*
|
||||
* @param domain 域名
|
||||
* @return 解码后的域名
|
||||
* @throws UtilException 计算异常
|
||||
*/
|
||||
public static String decodeDomain(final String domain) throws UtilException {
|
||||
Assert.notNull(domain, "domain must not be null!");
|
||||
final List<String> split = StrUtil.split(domain, CharUtil.DOT);
|
||||
final StringBuilder result = new StringBuilder(domain.length() / 4 + 1);
|
||||
for (final String str : split) {
|
||||
if (result.length() != 0) {
|
||||
result.append(CharUtil.DOT);
|
||||
}
|
||||
result.append(decode(str));
|
||||
}
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 解码 PunyCode为字符串
|
||||
*
|
||||
@@ -133,7 +178,8 @@ public class PunyCode {
|
||||
int n = INITIAL_N;
|
||||
int i = 0;
|
||||
int bias = INITIAL_BIAS;
|
||||
final StringBuilder output = new StringBuilder();
|
||||
final int length = input.length();
|
||||
final StringBuilder output = new StringBuilder(length / 4 + 1);
|
||||
int d = input.lastIndexOf(DELIMITER);
|
||||
if (d > 0) {
|
||||
for (int j = 0; j < d; j++) {
|
||||
@@ -146,7 +192,6 @@ public class PunyCode {
|
||||
} else {
|
||||
d = 0;
|
||||
}
|
||||
final int length = input.length();
|
||||
while (d < length) {
|
||||
final int oldi = i;
|
||||
int w = 1;
|
||||
|
@@ -8,6 +8,7 @@ import cn.hutool.core.lang.func.Func1;
|
||||
import cn.hutool.core.math.NumberUtil;
|
||||
import cn.hutool.core.regex.ReUtil;
|
||||
import cn.hutool.core.text.finder.CharFinder;
|
||||
import cn.hutool.core.text.finder.CharMatcherFinder;
|
||||
import cn.hutool.core.text.finder.Finder;
|
||||
import cn.hutool.core.text.finder.StrFinder;
|
||||
import cn.hutool.core.text.split.SplitUtil;
|
||||
@@ -743,11 +744,11 @@ public class CharSequenceUtil extends StrChecker {
|
||||
* @return 字符串含有非检查的字符,返回false
|
||||
* @since 4.4.1
|
||||
*/
|
||||
public static boolean containsAll(CharSequence str, CharSequence... testChars) {
|
||||
public static boolean containsAll(final CharSequence str, final CharSequence... testChars) {
|
||||
if (isBlank(str) || ArrayUtil.isEmpty(testChars)) {
|
||||
return false;
|
||||
}
|
||||
for (CharSequence testChar : testChars) {
|
||||
for (final CharSequence testChar : testChars) {
|
||||
if (false == contains(str, testChar)) {
|
||||
return false;
|
||||
}
|
||||
@@ -800,6 +801,23 @@ public class CharSequenceUtil extends StrChecker {
|
||||
return new CharFinder(searchChar).setText(text).setEndIndex(end).start(start);
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定范围内查找指定字符
|
||||
*
|
||||
* @param text 字符串
|
||||
* @param matcher 被查找的字符匹配器
|
||||
* @param start 起始位置,如果小于0,从0开始查找
|
||||
* @param end 终止位置,如果超过str.length()则默认查找到字符串末尾
|
||||
* @return 位置
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public static int indexOf(final CharSequence text, final Predicate<Character> matcher, final int start, final int end) {
|
||||
if (isEmpty(text)) {
|
||||
return INDEX_NOT_FOUND;
|
||||
}
|
||||
return new CharMatcherFinder(matcher).setText(text).setEndIndex(end).start(start);
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定范围内查找字符串,忽略大小写<br>
|
||||
*
|
||||
@@ -3182,6 +3200,46 @@ public class CharSequenceUtil extends StrChecker {
|
||||
|
||||
// ------------------------------------------------------------------------ replace
|
||||
|
||||
/**
|
||||
* 替换字符串中第一个指定字符串
|
||||
*
|
||||
* @param str 字符串
|
||||
* @param searchStr 被查找的字符串
|
||||
* @param replacedStr 被替换的字符串
|
||||
* @param ignoreCase 是否忽略大小写
|
||||
* @return 替换后的字符串
|
||||
*/
|
||||
public static String replaceFirst(final CharSequence str, final CharSequence searchStr, final CharSequence replacedStr, final boolean ignoreCase) {
|
||||
if (isEmpty(str)) {
|
||||
return str(str);
|
||||
}
|
||||
final int startInclude = indexOf(str, searchStr, 0, ignoreCase);
|
||||
if (INDEX_NOT_FOUND == startInclude) {
|
||||
return str(str);
|
||||
}
|
||||
return replace(str, startInclude, startInclude + searchStr.length(), replacedStr);
|
||||
}
|
||||
|
||||
/**
|
||||
* 替换字符串中最后一个指定字符串
|
||||
*
|
||||
* @param str 字符串
|
||||
* @param searchStr 被查找的字符串
|
||||
* @param replacedStr 被替换的字符串
|
||||
* @param ignoreCase 是否忽略大小写
|
||||
* @return 替换后的字符串
|
||||
*/
|
||||
public static String replaceLast(final CharSequence str, final CharSequence searchStr, final CharSequence replacedStr, final boolean ignoreCase) {
|
||||
if (isEmpty(str)) {
|
||||
return str(str);
|
||||
}
|
||||
final int lastIndex = lastIndexOf(str, searchStr, str.length(), ignoreCase);
|
||||
if (INDEX_NOT_FOUND == lastIndex) {
|
||||
return str(str);
|
||||
}
|
||||
return replace(str, lastIndex, searchStr, replacedStr, ignoreCase);
|
||||
}
|
||||
|
||||
/**
|
||||
* 替换字符串中的指定字符串,忽略大小写
|
||||
*
|
||||
|
@@ -6,7 +6,7 @@ import org.junit.Test;
|
||||
public class PunyCodeTest {
|
||||
|
||||
@Test
|
||||
public void encodeDecodeTest(){
|
||||
public void encodeDecodeTest() {
|
||||
final String text = "Hutool编码器";
|
||||
final String strPunyCode = PunyCode.encode(text);
|
||||
Assert.assertEquals("Hutool-ux9js33tgln", strPunyCode);
|
||||
@@ -15,4 +15,37 @@ public class PunyCodeTest {
|
||||
decode = PunyCode.decode("xn--Hutool-ux9js33tgln");
|
||||
Assert.assertEquals(text, decode);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void encodeDecodeDomainTest() {
|
||||
// 全中文
|
||||
final String text = "百度.中国";
|
||||
final String strPunyCode = PunyCode.encodeDomain(text);
|
||||
Assert.assertEquals("xn--wxtr44c.xn--fiqs8s", strPunyCode);
|
||||
|
||||
final String decode = PunyCode.decodeDomain(strPunyCode);
|
||||
Assert.assertEquals(text, decode);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void encodeDecodeDomainTest2() {
|
||||
// 中英文分段
|
||||
final String text = "hutool.中国";
|
||||
final String strPunyCode = PunyCode.encodeDomain(text);
|
||||
Assert.assertEquals("xn--hutool-.xn--fiqs8s", strPunyCode);
|
||||
|
||||
final String decode = PunyCode.decodeDomain(strPunyCode);
|
||||
Assert.assertEquals(text, decode);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void encodeDecodeDomainTest3() {
|
||||
// 中英文混合
|
||||
final String text = "hutool工具.中国";
|
||||
final String strPunyCode = PunyCode.encodeDomain(text);
|
||||
Assert.assertEquals("xn--hutool-up2j943f.xn--fiqs8s", strPunyCode);
|
||||
|
||||
final String decode = PunyCode.decodeDomain(strPunyCode);
|
||||
Assert.assertEquals(text, decode);
|
||||
}
|
||||
}
|
||||
|
@@ -195,4 +195,18 @@ public class CharSequenceUtilTest {
|
||||
(v) -> DateUtil.parse(v, DatePattern.NORM_DATETIME_PATTERN).toInstant(), Instant::now);
|
||||
Assert.assertNotNull(result2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void replaceLastTest() {
|
||||
final String str = "i am jack and jack";
|
||||
final String result = StrUtil.replaceLast(str, "JACK", null, true);
|
||||
Assert.assertEquals(result, "i am jack and ");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void replaceFirstTest() {
|
||||
final String str = "yes and yes i do";
|
||||
final String result = StrUtil.replaceFirst(str, "YES", "", true);
|
||||
Assert.assertEquals(result, " and yes i do");
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user