diff --git a/hutool-core/src/main/java/cn/hutool/v7/core/codec/binary/HexUtil.java b/hutool-core/src/main/java/cn/hutool/v7/core/codec/binary/HexUtil.java
index 5c567247e..59c0212da 100644
--- a/hutool-core/src/main/java/cn/hutool/v7/core/codec/binary/HexUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/v7/core/codec/binary/HexUtil.java
@@ -16,7 +16,6 @@
package cn.hutool.v7.core.codec.binary;
-import cn.hutool.v7.core.text.CharUtil;
import cn.hutool.v7.core.text.StrUtil;
import java.awt.Color;
@@ -249,16 +248,42 @@ public class HexUtil extends Hex {
* @param prefix 自定义前缀,如0x
* @return 格式化后的字符串
*/
- public static String format(final String hexStr, String prefix) {
+ public static String format(final String hexStr, final String prefix) {
+ return format(hexStr, prefix, StrUtil.SPACE);
+ }
+
+ /**
+ * 格式化Hex字符串,结果为每2位加一个空格,类似于:
+ *
+ * e8 8c 67 03 80 cb 22 00 95 26 8f
+ *
+ *
+ * @param hexStr Hex字符串
+ * @param prefix 自定义前缀,如0x
+ * @param separator 自定义分隔符,如空格
+ * @return 格式化后的字符串
+ */
+ public static String format(final String hexStr, String prefix, String separator) {
+ if (StrUtil.isEmpty(hexStr)) {
+ return StrUtil.EMPTY;
+ }
if (null == prefix) {
prefix = StrUtil.EMPTY;
}
+ if (null == separator) {
+ separator = StrUtil.SPACE;
+ }
final int length = hexStr.length();
final StringBuilder builder = StrUtil.builder(length + length / 2 + (length / 2 * prefix.length()));
- builder.append(prefix).append(hexStr.charAt(0)).append(hexStr.charAt(1));
- for (int i = 2; i < length - 1; i += 2) {
- builder.append(CharUtil.SPACE).append(prefix).append(hexStr.charAt(i)).append(hexStr.charAt(i + 1));
+ for (int i = 0; i < length; i++) {
+ if (i % 2 == 0) {
+ if (i != 0) {
+ builder.append(separator);
+ }
+ builder.append(prefix);
+ }
+ builder.append(hexStr.charAt(i));
}
return builder.toString();
}
diff --git a/hutool-core/src/main/java/cn/hutool/v7/core/text/split/SplitIter.java b/hutool-core/src/main/java/cn/hutool/v7/core/text/split/SplitIter.java
index 869dbabdc..6ce62d540 100644
--- a/hutool-core/src/main/java/cn/hutool/v7/core/text/split/SplitIter.java
+++ b/hutool-core/src/main/java/cn/hutool/v7/core/text/split/SplitIter.java
@@ -89,29 +89,28 @@ public class SplitIter extends ComputeIter implements Serializable {
return text.substring(offset);
}
- final int start = finder.start(offset);
- // 无分隔符,结束
- if (start < 0) {
- // 如果不再有分隔符,但是遗留了字符,则单独作为一个段
- if (offset <= text.length()) {
- final String result = text.substring(offset);
- if (!ignoreEmpty || !result.isEmpty()) {
- // 返回非空串
- offset = Integer.MAX_VALUE;
- return result;
+ String result;
+ int start;
+ do {
+ start = finder.start(offset);
+ // 无分隔符,结束
+ if (start < 0) {
+ // 如果不再有分隔符,但是遗留了字符,则单独作为一个段
+ if (offset <= text.length()) {
+ result = text.substring(offset);
+ if (!ignoreEmpty || !result.isEmpty()) {
+ // 返回非空串
+ offset = Integer.MAX_VALUE;
+ return result;
+ }
}
+ return null;
}
- return null;
- }
- // 找到新的分隔符位置
- final String result = text.substring(offset, start);
- offset = finder.end(start);
-
- if (ignoreEmpty && result.isEmpty()) {
- // 发现空串且需要忽略时,跳过之
- return computeNext();
- }
+ // 找到新的分隔符位置
+ result = text.substring(offset, start);
+ offset = finder.end(start);
+ } while (ignoreEmpty && result.isEmpty()); // 空串则继续循环
count++;
return result;
diff --git a/hutool-core/src/test/java/cn/hutool/v7/core/text/split/SplitIterTest.java b/hutool-core/src/test/java/cn/hutool/v7/core/text/split/SplitIterTest.java
index d491e9235..c8406ea4f 100644
--- a/hutool-core/src/test/java/cn/hutool/v7/core/text/split/SplitIterTest.java
+++ b/hutool-core/src/test/java/cn/hutool/v7/core/text/split/SplitIterTest.java
@@ -23,9 +23,12 @@ import cn.hutool.v7.core.text.finder.StrFinder;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
+import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
public class SplitIterTest {
@Test
@@ -38,7 +41,7 @@ public class SplitIterTest {
Integer.MAX_VALUE,
false
);
- Assertions.assertEquals(6, splitIter.toList(false).size());
+ assertEquals(6, splitIter.toList(false).size());
}
@Test
@@ -51,7 +54,7 @@ public class SplitIterTest {
Integer.MAX_VALUE,
false
);
- Assertions.assertEquals(4, splitIter.toList(false).size());
+ assertEquals(4, splitIter.toList(false).size());
}
@Test
@@ -65,7 +68,7 @@ public class SplitIterTest {
);
final List strings = splitIter.toList(false);
- Assertions.assertEquals(4, strings.size());
+ assertEquals(4, strings.size());
}
@Test
@@ -79,10 +82,10 @@ public class SplitIterTest {
);
final List strings = splitIter.toList(true);
- Assertions.assertEquals(3, strings.size());
- Assertions.assertEquals("a", strings.get(0));
- Assertions.assertEquals("efedsfs", strings.get(1));
- Assertions.assertEquals("ddf", strings.get(2));
+ assertEquals(3, strings.size());
+ assertEquals("a", strings.get(0));
+ assertEquals("efedsfs", strings.get(1));
+ assertEquals("ddf", strings.get(2));
}
@Test
@@ -96,7 +99,7 @@ public class SplitIterTest {
);
final List strings = splitIter.toList(false);
- Assertions.assertEquals(3, strings.size());
+ assertEquals(3, strings.size());
}
@Test
@@ -110,7 +113,7 @@ public class SplitIterTest {
);
final List strings = splitIter.toList(false);
- Assertions.assertEquals(3, strings.size());
+ assertEquals(3, strings.size());
}
@Test
@@ -123,7 +126,7 @@ public class SplitIterTest {
);
final List strings = splitIter.toList(false);
- Assertions.assertEquals(4, strings.size());
+ assertEquals(4, strings.size());
}
@Test
@@ -136,7 +139,7 @@ public class SplitIterTest {
);
final List strings = splitIter.toList(false);
- Assertions.assertEquals(3, strings.size());
+ assertEquals(3, strings.size());
}
@Test
@@ -149,7 +152,7 @@ public class SplitIterTest {
);
final List strings = splitIter.toList(false);
- Assertions.assertEquals(1, strings.size());
+ assertEquals(1, strings.size());
}
// 切割字符串是空字符串时报错
@@ -164,7 +167,21 @@ public class SplitIterTest {
);
final List strings = splitIter.toList(false);
- Assertions.assertEquals(1, strings.size());
+ assertEquals(1, strings.size());
});
}
+
+ @Test
+ public void issue4169Test() {
+ final StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < 20000; i++) { // 1万次连续分隔符,模拟递归深度风险场景
+ sb.append(",");
+ }
+ sb.append("test");
+
+ final SplitIter iter = new SplitIter(sb.toString(), new StrFinder(",",false), 0, true);
+ final List result = iter.toList(false);
+
+ assertEquals(Collections.singletonList("test"), result);
+ }
}
diff --git a/hutool-core/src/test/java/cn/hutool/v7/core/util/HexUtilTest.java b/hutool-core/src/test/java/cn/hutool/v7/core/util/HexUtilTest.java
index 8cc4e564a..3c14f9b55 100644
--- a/hutool-core/src/test/java/cn/hutool/v7/core/util/HexUtilTest.java
+++ b/hutool-core/src/test/java/cn/hutool/v7/core/util/HexUtilTest.java
@@ -135,4 +135,34 @@ public class HexUtilTest {
final String hex3 = "#FF";
assertEquals(new BigInteger("FF", 16), HexUtil.toBigInteger(hex3));
}
+
+ @Test
+ public void testFormatEmpty() {
+ final String result = HexUtil.format("");
+ assertEquals("", result);
+ }
+
+ @Test
+ public void testFormatSingleChar() {
+ final String result = HexUtil.format("1");
+ assertEquals("1", result);
+ }
+
+ @Test
+ public void testFormatOddLength() {
+ final String result = HexUtil.format("123");
+ assertEquals("12 3", result);
+ }
+
+ @Test
+ public void testFormatWithPrefixSingleChar() {
+ final String result = HexUtil.format("1", "0x");
+ assertEquals("0x1", result);
+ }
+
+ @Test
+ public void testFormatWithPrefixOddLength() {
+ final String result = HexUtil.format("123", "0x");
+ assertEquals("0x12 0x3", result);
+ }
}