diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6c9a44e66..e480ed309 100755
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -16,6 +16,7 @@
* 【core 】 由于对于ASCII的编码解码有缺陷,且这种BCD实现并不规范,因此BCD标记为弃用(issue#I5XEC6@Gitee)
* 【core 】 修复IoUtil.copyByNIO方法写出时没有flush的问题
* 【core 】 修复TreeBuilder中使用HashMap导致默认乱序问题(issue#I5Z8C5@Gitee)
+* 【core 】 修复StrUtil.subWithLength负数问题(issue#I5YN49@Gitee)
-------------------------------------------------------------------------------------------------------------
# 5.8.9 (2022-10-22)
diff --git a/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java b/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java
index 4b5e7e577..10549f357 100755
--- a/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java
@@ -2132,15 +2132,22 @@ public class CharSequenceUtil {
/**
* 截取字符串,从指定位置开始,截取指定长度的字符串
- * author weibaohui
+ * 如果fromIndex为正数,则向后截取指定length长度,如果为负数,则向前截取length长度。
*
* @param input 原始字符串
* @param fromIndex 开始的index,包括
* @param length 要截取的长度
* @return 截取后的字符串
+ * @author weibaohui
*/
public static String subWithLength(String input, int fromIndex, int length) {
- return sub(input, fromIndex, fromIndex + length);
+ final int toIndex;
+ if(fromIndex < 0){
+ toIndex = fromIndex - length;
+ }else{
+ toIndex = fromIndex + length;
+ }
+ return sub(input, fromIndex, toIndex);
}
/**
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 6a221a833..13d1976be 100755
--- a/hutool-core/src/test/java/cn/hutool/core/util/StrUtilTest.java
+++ b/hutool-core/src/test/java/cn/hutool/core/util/StrUtilTest.java
@@ -15,14 +15,14 @@ public class StrUtilTest {
@Test
public void isBlankTest() {
- String blank = " ";
+ final String blank = " ";
Assert.assertTrue(StrUtil.isBlank(blank));
}
@Test
public void trimTest() {
- String blank = " 哈哈 ";
- String trim = StrUtil.trim(blank);
+ final String blank = " 哈哈 ";
+ final String trim = StrUtil.trim(blank);
Assert.assertEquals("哈哈", trim);
}
@@ -40,29 +40,29 @@ public class StrUtilTest {
@Test
public void trimTabTest() {
- String str = "\taaa";
+ final String str = "\taaa";
Assert.assertEquals("aaa", StrUtil.trim(str));
}
@Test
public void cleanBlankTest() {
// 包含:制表符、英文空格、不间断空白符、全角空格
- String str = " 你 好 ";
- String cleanBlank = StrUtil.cleanBlank(str);
+ final String str = " 你 好 ";
+ final String cleanBlank = StrUtil.cleanBlank(str);
Assert.assertEquals("你好", cleanBlank);
}
@Test
public void cutTest() {
- String str = "aaabbbcccdddaadfdfsdfsdf0";
- String[] cut = StrUtil.cut(str, 4);
+ final String str = "aaabbbcccdddaadfdfsdfsdf0";
+ final String[] cut = StrUtil.cut(str, 4);
Assert.assertArrayEquals(new String[]{"aaab", "bbcc", "cddd", "aadf", "dfsd", "fsdf", "0"}, cut);
}
@Test
public void splitTest() {
- String str = "a,b ,c,d,,e";
- List split = StrUtil.split(str, ',', -1, true, true);
+ final String str = "a,b ,c,d,,e";
+ final List split = StrUtil.split(str, ',', -1, true, true);
// 测试空是否被去掉
Assert.assertEquals(5, split.size());
// 测试去掉两边空白符是否生效
@@ -74,16 +74,16 @@ public class StrUtilTest {
@Test
public void splitEmptyTest() {
- String str = "";
- List split = StrUtil.split(str, ',', -1, true, true);
+ final String str = "";
+ final List split = StrUtil.split(str, ',', -1, true, true);
// 测试空是否被去掉
Assert.assertEquals(0, split.size());
}
@Test
public void splitTest2() {
- String str = "a.b.";
- List split = StrUtil.split(str, '.');
+ final String str = "a.b.";
+ final List split = StrUtil.split(str, '.');
Assert.assertEquals(3, split.size());
Assert.assertEquals("b", split.get(1));
Assert.assertEquals("", split.get(2));
@@ -101,7 +101,7 @@ public class StrUtilTest {
@Test
public void splitToLongTest() {
- String str = "1,2,3,4, 5";
+ final String str = "1,2,3,4, 5";
long[] longArray = StrUtil.splitToLong(str, ',');
Assert.assertArrayEquals(new long[]{1, 2, 3, 4, 5}, longArray);
@@ -111,7 +111,7 @@ public class StrUtilTest {
@Test
public void splitToIntTest() {
- String str = "1,2,3,4, 5";
+ final String str = "1,2,3,4, 5";
int[] intArray = StrUtil.splitToInt(str, ',');
Assert.assertArrayEquals(new int[]{1, 2, 3, 4, 5}, intArray);
@@ -121,11 +121,11 @@ public class StrUtilTest {
@Test
public void formatTest() {
- String template = "你好,我是{name},我的电话是:{phone}";
- String result = StrUtil.format(template, Dict.create().set("name", "张三").set("phone", "13888881111"));
+ final String template = "你好,我是{name},我的电话是:{phone}";
+ final String result = StrUtil.format(template, Dict.create().set("name", "张三").set("phone", "13888881111"));
Assert.assertEquals("你好,我是张三,我的电话是:13888881111", result);
- String result2 = StrUtil.format(template, Dict.create().set("name", "张三").set("phone", null));
+ final String result2 = StrUtil.format(template, Dict.create().set("name", "张三").set("phone", null));
Assert.assertEquals("你好,我是张三,我的电话是:{phone}", result2);
}
@@ -191,8 +191,8 @@ public class StrUtilTest {
@Test
public void lastIndexOfTest() {
- String a = "aabbccddcc";
- int lastIndexOf = StrUtil.lastIndexOf(a, "c", 0, false);
+ final String a = "aabbccddcc";
+ final int lastIndexOf = StrUtil.lastIndexOf(a, "c", 0, false);
Assert.assertEquals(-1, lastIndexOf);
}
@@ -222,76 +222,76 @@ public class StrUtilTest {
@Test
public void replaceTest2() {
- String result = StrUtil.replace("123", "2", "3");
+ final String result = StrUtil.replace("123", "2", "3");
Assert.assertEquals("133", result);
}
@Test
public void replaceTest3() {
- String result = StrUtil.replace(",abcdef,", ",", "|");
+ final String result = StrUtil.replace(",abcdef,", ",", "|");
Assert.assertEquals("|abcdef|", result);
}
@Test
public void replaceTest4() {
- String a = "1039";
- String result = StrUtil.padPre(a, 8, "0"); //在字符串1039前补4个0
+ final String a = "1039";
+ final String result = StrUtil.padPre(a, 8, "0"); //在字符串1039前补4个0
Assert.assertEquals("00001039", result);
- String aa = "1039";
- String result1 = StrUtil.padPre(aa, -1, "0"); //在字符串1039前补4个0
+ final String aa = "1039";
+ final String result1 = StrUtil.padPre(aa, -1, "0"); //在字符串1039前补4个0
Assert.assertEquals("103", result1);
}
@Test
public void replaceTest5() {
- String a = "\uD853\uDC09秀秀";
- String result = StrUtil.replace(a, 1, a.length(), '*');
+ final String a = "\uD853\uDC09秀秀";
+ final String result = StrUtil.replace(a, 1, a.length(), '*');
Assert.assertEquals("\uD853\uDC09**", result);
- String aa = "规划大师";
- String result1 = StrUtil.replace(aa, 2, a.length(), '*');
+ final String aa = "规划大师";
+ final String result1 = StrUtil.replace(aa, 2, a.length(), '*');
Assert.assertEquals("规划**", result1);
}
@Test
public void upperFirstTest() {
- StringBuilder sb = new StringBuilder("KEY");
- String s = StrUtil.upperFirst(sb);
+ final StringBuilder sb = new StringBuilder("KEY");
+ final String s = StrUtil.upperFirst(sb);
Assert.assertEquals(s, sb.toString());
}
@Test
public void lowerFirstTest() {
- StringBuilder sb = new StringBuilder("KEY");
- String s = StrUtil.lowerFirst(sb);
+ final StringBuilder sb = new StringBuilder("KEY");
+ final String s = StrUtil.lowerFirst(sb);
Assert.assertEquals("kEY", s);
}
@Test
public void subTest() {
- String a = "abcderghigh";
- String pre = StrUtil.sub(a, -5, a.length());
+ final String a = "abcderghigh";
+ final 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";
+ final String test = "\uD83E\uDD14\uD83D\uDC4D\uD83C\uDF53\uD83E\uDD14";
// 不正确的子字符串
- String wrongAnswer = StrUtil.sub(test, 0, 3);
+ final String wrongAnswer = StrUtil.sub(test, 0, 3);
Assert.assertNotEquals("\uD83E\uDD14\uD83D\uDC4D\uD83C\uDF53", wrongAnswer);
// 正确的子字符串
- String rightAnswer = StrUtil.subByCodePoint(test, 0, 3);
+ final String rightAnswer = StrUtil.subByCodePoint(test, 0, 3);
Assert.assertEquals("\uD83E\uDD14\uD83D\uDC4D\uD83C\uDF53", rightAnswer);
}
@Test
public void subBeforeTest() {
- String a = "abcderghigh";
+ final String a = "abcderghigh";
String pre = StrUtil.subBefore(a, "d", false);
Assert.assertEquals("abc", pre);
pre = StrUtil.subBefore(a, 'd', false);
@@ -308,7 +308,7 @@ public class StrUtilTest {
@Test
public void subAfterTest() {
- String a = "abcderghigh";
+ final String a = "abcderghigh";
String pre = StrUtil.subAfter(a, "d", false);
Assert.assertEquals("erghigh", pre);
pre = StrUtil.subAfter(a, 'd', false);
@@ -346,7 +346,7 @@ public class StrUtilTest {
@Test
public void moveTest() {
- String str = "aaaaaaa22222bbbbbbb";
+ final String str = "aaaaaaa22222bbbbbbb";
String result = StrUtil.move(str, 7, 12, -3);
Assert.assertEquals("aaaa22222aaabbbbbbb", result);
result = StrUtil.move(str, 7, 12, -4);
@@ -369,7 +369,7 @@ public class StrUtilTest {
@Test
public void removePrefixIgnorecaseTest() {
- String a = "aaabbb";
+ final String a = "aaabbb";
String prefix = "aaa";
Assert.assertEquals("bbb", StrUtil.removePrefixIgnoreCase(a, prefix));
@@ -382,7 +382,7 @@ public class StrUtilTest {
@Test
public void maxLengthTest() {
- String text = "我是一段正文,很长的正文,需要截取的正文";
+ final String text = "我是一段正文,很长的正文,需要截取的正文";
String str = StrUtil.maxLength(text, 5);
Assert.assertEquals("我是一段正...", str);
str = StrUtil.maxLength(text, 21);
@@ -457,31 +457,31 @@ public class StrUtilTest {
@Test
public void subBetweenAllTest2() {
//issue#861@Github,起始不匹配的时候,应该直接空
- String src1 = "/* \n* hutool */ asdas /* \n* hutool */";
- String src2 = "/ * hutool */ asdas / * hutool */";
+ final String src1 = "/* \n* hutool */ asdas /* \n* hutool */";
+ final String src2 = "/ * hutool */ asdas / * hutool */";
- String[] results1 = StrUtil.subBetweenAll(src1, "/**", "*/");
+ final String[] results1 = StrUtil.subBetweenAll(src1, "/**", "*/");
Assert.assertEquals(0, results1.length);
- String[] results2 = StrUtil.subBetweenAll(src2, "/*", "*/");
+ final String[] results2 = StrUtil.subBetweenAll(src2, "/*", "*/");
Assert.assertEquals(0, results2.length);
}
@Test
public void subBetweenAllTest3() {
- String src1 = "'abc'and'123'";
+ final String src1 = "'abc'and'123'";
String[] strings = StrUtil.subBetweenAll(src1, "'", "'");
Assert.assertEquals(2, strings.length);
Assert.assertEquals("abc", strings[0]);
Assert.assertEquals("123", strings[1]);
- String src2 = "'abc''123'";
+ final String src2 = "'abc''123'";
strings = StrUtil.subBetweenAll(src2, "'", "'");
Assert.assertEquals(2, strings.length);
Assert.assertEquals("abc", strings[0]);
Assert.assertEquals("123", strings[1]);
- String src3 = "'abc'123'";
+ final String src3 = "'abc'123'";
strings = StrUtil.subBetweenAll(src3, "'", "'");
Assert.assertEquals(1, strings.length);
Assert.assertEquals("abc", strings[0]);
@@ -489,8 +489,8 @@ public class StrUtilTest {
@Test
public void subBetweenAllTest4() {
- String str = "你好:1388681xxxx用户已开通,1877275xxxx用户已开通,无法发送业务开通短信";
- String[] strings = StrUtil.subBetweenAll(str, "1877275xxxx", ",");
+ final String str = "你好:1388681xxxx用户已开通,1877275xxxx用户已开通,无法发送业务开通短信";
+ final String[] strings = StrUtil.subBetweenAll(str, "1877275xxxx", ",");
Assert.assertEquals(1, strings.length);
Assert.assertEquals("用户已开通", strings[0]);
}
@@ -498,9 +498,9 @@ public class StrUtilTest {
@Test
public void briefTest() {
// case: 1 至 str.length - 1
- String str = RandomUtil.randomString(RandomUtil.randomInt(1, 100));
+ final String str = RandomUtil.randomString(RandomUtil.randomInt(1, 100));
for (int maxLength = 1; maxLength < str.length(); maxLength++) {
- String brief = StrUtil.brief(str, maxLength);
+ final String brief = StrUtil.brief(str, maxLength);
Assert.assertEquals(brief.length(), maxLength);
}
@@ -513,7 +513,7 @@ public class StrUtilTest {
@Test
public void briefTest2() {
- String str = "123";
+ final String str = "123";
int maxLength = 3;
String brief = StrUtil.brief(str, maxLength);
Assert.assertEquals("123", brief);
@@ -529,7 +529,7 @@ public class StrUtilTest {
@Test
public void briefTest3() {
- String str = "123abc";
+ final String str = "123abc";
int maxLength = 6;
String brief = StrUtil.brief(str, maxLength);
@@ -560,7 +560,7 @@ public class StrUtilTest {
public void filterTest() {
final String filterNumber = StrUtil.filter("hutool678", CharUtil::isNumber);
Assert.assertEquals("678", filterNumber);
- String cleanBlank = StrUtil.filter(" 你 好 ", c -> !CharUtil.isBlankChar(c));
+ final String cleanBlank = StrUtil.filter(" 你 好 ", c -> !CharUtil.isBlankChar(c));
Assert.assertEquals("你好", cleanBlank);
}
@@ -575,8 +575,8 @@ public class StrUtilTest {
@Test
public void startWithTest() {
- String a = "123";
- String b = "123";
+ final String a = "123";
+ final String b = "123";
Assert.assertTrue(StrUtil.startWith(a, b));
Assert.assertFalse(StrUtil.startWithIgnoreEquals(a, b));
@@ -602,33 +602,39 @@ public class StrUtilTest {
@Test
public void isCharEqualsTest() {
- String a = "aaaaaaaaa";
+ final String a = "aaaaaaaaa";
Assert.assertTrue(StrUtil.isCharEquals(a));
}
@Test
public void isNumericTest() {
- String a = "2142342422423423";
+ final String a = "2142342422423423";
Assert.assertTrue(StrUtil.isNumeric(a));
}
@Test
public void containsAllTest() {
- String a = "2142342422423423";
+ final String a = "2142342422423423";
Assert.assertTrue(StrUtil.containsAll(a, "214", "234"));
}
@Test
public void replaceLastTest() {
- String str = "i am jackjack";
- String result = StrUtil.replaceLast(str, "JACK", null, true);
+ final String str = "i am jackjack";
+ final String result = StrUtil.replaceLast(str, "JACK", null, true);
Assert.assertEquals(result, "i am jack");
}
@Test
public void replaceFirstTest() {
- String str = "yesyes i do";
- String result = StrUtil.replaceFirst(str, "YES", "", true);
+ final String str = "yesyes i do";
+ final String result = StrUtil.replaceFirst(str, "YES", "", true);
Assert.assertEquals(result, "yes i do");
}
+
+ @Test
+ public void issueI5YN49Test() {
+ final String str = "A5E6005700000000000000000000000000000000000000090D0100000000000001003830";
+ Assert.assertEquals("38", StrUtil.subWithLength(str,-2,2));
+ }
}