From 48a057c52d1c1aac35d926d446ad70b121fe942d Mon Sep 17 00:00:00 2001 From: pantao Date: Tue, 10 Dec 2019 18:59:33 +0800 Subject: [PATCH] feat: support emoji substring --- .../java/cn/hutool/core/util/StrUtil.java | 27 +++++++++++++++++++ .../java/cn/hutool/core/util/StrUtilTest.java | 14 ++++++++++ 2 files changed, 41 insertions(+) diff --git a/hutool-core/src/main/java/cn/hutool/core/util/StrUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/StrUtil.java index 5b41e0a0c..39da66a18 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/StrUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/StrUtil.java @@ -1579,6 +1579,33 @@ public class StrUtil { return str.toString().substring(fromIndex, toIndex); } + /** + * 通过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 * diff --git a/hutool-core/src/test/java/cn/hutool/core/util/StrUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/StrUtilTest.java index dbaf1f254..f4d537426 100644 --- a/hutool-core/src/test/java/cn/hutool/core/util/StrUtilTest.java +++ b/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() {