Browse Source

feat: support emoji substring

pantao 6 years ago
parent
commit
48a057c52d

+ 27 - 0
hutool-core/src/main/java/cn/hutool/core/util/StrUtil.java

@@ -1580,6 +1580,33 @@ public class StrUtil {
 	}
 
 	/**
+	 * 通过CodePoint截取字符串,可以截断Emoji
+	 *
+	 * @param str String
+	 * @param fromIndex 开始的index(包括)
+	 * @param toIndex 结束的index(不包括)
+	 * @return 字串
+	 */
+	public static String subByCodePoint(CharSequence str, int fromIndex, int toIndex) {
+		if (isEmpty(str)) {
+			return str(str);
+		}
+
+		if (fromIndex < 0 || fromIndex > toIndex) {
+			throw new IllegalArgumentException();
+		}
+
+		if (fromIndex == toIndex) {
+			return EMPTY;
+		}
+
+		StringBuilder sb = new StringBuilder();
+		int subLen = toIndex - fromIndex;
+		str.toString().codePoints().skip(fromIndex).limit(subLen).forEach(v -> sb.append(Character.toChars(v)));
+		return sb.toString();
+	}
+
+	/**
 	 * 截取部分字符串,这里一个汉字的长度认为是2
 	 *
 	 * @param str 字符串

+ 14 - 0
hutool-core/src/test/java/cn/hutool/core/util/StrUtilTest.java

@@ -218,6 +218,20 @@ public class StrUtilTest {
 		String pre = StrUtil.sub(a, -5, a.length());
 		Assert.assertEquals("ghigh", pre);
 	}
+
+	@Test
+	public void subByCodePointTest() {
+		// 🤔👍🍓🤔
+		String test = "\uD83E\uDD14\uD83D\uDC4D\uD83C\uDF53\uD83E\uDD14";
+
+		// 不正确的子字符串
+		String wrongAnswer = StrUtil.sub(test, 0, 3);
+		Assert.assertNotEquals("\uD83E\uDD14\uD83D\uDC4D\uD83C\uDF53", wrongAnswer);
+
+		// 正确的子字符串
+		String rightAnswer = StrUtil.subByCodePoint(test, 0, 3);
+		Assert.assertEquals("\uD83E\uDD14\uD83D\uDC4D\uD83C\uDF53", rightAnswer);
+	}
 	
 	@Test
 	public void subBeforeTest() {