修复StrUtil.truncateByByteLength在限制长度小于...时报错问题(issue#IDFTJS@Gitee)

This commit is contained in:
Looly
2025-12-27 13:05:59 +08:00
parent 32c9c2836f
commit 723e495b3c
3 changed files with 25 additions and 14 deletions

View File

@@ -30,6 +30,7 @@
* 【core 】 修复`SplitIter.reset`后无法重新迭代的问题pr#1418@Gitee
* 【core 】 修复`StrMatcher`连续变量解析导致的歧义问题pr#1419@Gitee
* 【ai 】 修复`BaseAIService`发送请求方法中try/catch块捕获的应该是Exception而不是自定义的AIExceptionpr#1430@Gitee
* 【core 】 修复`StrUtil.truncateByByteLength`在限制长度小于...时报错问题issue#IDFTJS@Gitee
-------------------------------------------------------------------------------------------------------------
# 5.8.42(2025-11-28)

View File

@@ -288,7 +288,7 @@ public class StrUtil extends CharSequenceUtil implements StrPool {
*
* @param obj 对象
* @return {@link String }
* @author Junwei Xu
* @author Junwei Xu
*/
public static String toStringOrEmpty(Object obj) {
// obj为空时, 返回 null 或 "null" 都不适用部分场景, 此处返回 "" 空字符串
@@ -379,6 +379,7 @@ public class StrUtil extends CharSequenceUtil implements StrPool {
* 该方法按Unicode code point进行反转支持Unicode字符的正确反转
* 确保复杂字符不会被拆分,如表情符号等多字节字符
* </p>
*
* @param str 被反转的字符串
* @return 反转后的字符串如果输入为null则返回null
* @since 5.8.43
@@ -536,29 +537,31 @@ public class StrUtil extends CharSequenceUtil implements StrPool {
* 此方法用于截取总bytes数不超过指定长度如果字符出没有超出原样输出如果超出了则截取掉超出部分并可选添加...
* 但是添加“...”后总长度也不超过限制长度。
*
* @param str 原始字符串
* @param charset 指定编码
* @param maxBytes 最大字节数
* @param factor 速算因子,取该编码下单个字符的最大可能字节数
* @param appendDots 截断后是否追加省略号(...)
* @param str 原始字符串
* @param charset 指定编码
* @param maxBytesLength 最大字节数
* @param factor 速算因子,取该编码下单个字符的最大可能字节数
* @param appendDots 截断后是否追加省略号...如果maxBytesLength小于省略号长度则不添加...
* @return 截断后的字符串
*/
public static String truncateByByteLength(String str, Charset charset, int maxBytes, int factor,
boolean appendDots) {
public static String truncateByByteLength(String str, Charset charset, int maxBytesLength, int factor,
boolean appendDots) {
//字符数*速算因子<=最大字节数
if (str == null || str.length() * factor <= maxBytes) {
if (str == null || str.length() * factor <= maxBytesLength) {
return str;
}
final byte[] sba = str.getBytes(charset);
if (sba.length <= maxBytes) {
if (sba.length <= maxBytesLength) {
return str;
}
//限制字节数
final int dotsBytesLength = "...".getBytes(charset).length;
final int limitBytes;
if (appendDots) {
limitBytes = maxBytes - "...".getBytes(charset).length;
// issue#IDFTJS 修正截断后追加省略号...导致超出限制长度的问题
if (appendDots && maxBytesLength > dotsBytesLength) {
limitBytes = maxBytesLength - "...".getBytes(charset).length;
} else {
limitBytes = maxBytes;
limitBytes = maxBytesLength;
}
final ByteBuffer bb = ByteBuffer.wrap(sba, 0, limitBytes);
final CharBuffer cb = CharBuffer.allocate(limitBytes);
@@ -568,7 +571,7 @@ public class StrUtil extends CharSequenceUtil implements StrPool {
decoder.decode(bb, cb, true);
decoder.flush(cb);
final String result = new String(cb.array(), 0, cb.position());
if (appendDots) {
if (appendDots && maxBytesLength > dotsBytesLength) {
return result + "...";
}
return result;

View File

@@ -719,4 +719,11 @@ public class StrUtilTest {
final String ret = StrUtil.truncateByByteLength(str, StandardCharsets.ISO_8859_1, 10, 1, false);
assertEquals("This is En", ret);
}
@Test
public void issueTest() {
final String s = "abc";
final String r = StrUtil.truncateByByteLength(s, CharsetUtil.CHARSET_UTF_8, 2, 4, true);
assertEquals("ab", r);
}
}