根据字符串长度修剪字符串


Answers:


262
s = s.substring(0, Math.min(s.length(), 10));

这样使用Math.min字符串可以避免在字符串早于的情况下出现异常10


笔记:

  1. 上面做了真正的修剪。如果您实际上想将截断的最后三个(!)字符替换为点,请使用Apache Commons StringUtils.abbreviate

  2. 如果您的字符串包含BMP之外的Unicode代码点,则此行为可能不正确1。例如表情符号。有关适用于所有Unicode代码点的(更复杂的)解决方案,请参见@sibnick的解决方案


1-不在平面0(BMP)上的Unicode代码点在中表示为“代理对”(即两个char值)String。通过忽略这一点,我们可能会修剪到少于10个代码点,或者(更糟)在代理对中间截断。另一方面,String.length()不再是Unicode文本长度的理想度量,因此基于它的修剪可能是错误的事情。


不能代替Math.min进行条件检查,并且仅当string为max时才需要子字符串吗?例如:s = (s.length() > 10) ? s.substring(0,10) : s ;
拉姆

1
是的,当然可以。阅读其他答案以了解解决问题的其他方法!
Stephen C

132

StringUtils.abbreviate来自Apache Commons Lang库的人可能是您的朋友:

StringUtils.abbreviate("abcdefg", 6) = "abc..."
StringUtils.abbreviate("abcdefg", 7) = "abcdefg"
StringUtils.abbreviate("abcdefg", 8) = "abcdefg"
StringUtils.abbreviate("abcdefg", 4) = "a..."

Commons Lang3甚至允许将自定义String设置为替换标记。这样,您可以例如设置单个字符的省略号。

StringUtils.abbreviate("abcdefg", "\u2026", 6) = "abcde…"

5
可以,但是OP的问题并不要求“省略号”。
2014年

9
@StephenC-问题显示8个字符,后跟2个点,给定的长度限制为10,这很像省略号(仅2个点而不是3个点)。许多发现此问题的人也可能会认为省略号很有用。
制造商史蒂夫(Steve)2014年

12
...如果您不希望使用省略号,那么StringUtils.left()可以为您提供帮助。
Superole

1
仅供参考,水平省略号是单个字符,而不是三个FULL STOP字符:…
Basil Bourque

53

有一个Apache Commons StringUtils函数可以做到这一点。

s = StringUtils.left(s, 10)

如果len个字符不可用,或者String为null,则将无例外返回String。如果len为负,则返回一个空字符串。

StringUtils.left(null,)= null
StringUtils.left(
,-ve)=“”
StringUtils.left(“”,*)=“”
StringUtils.left(“ abc”,0)=“”
StringUtils.left(“ abc“,2)=” ab“
StringUtils.left(” abc“,4)=” abc“

StringUtils.Left JavaDocs

图片提供:Steeve McCauley


22

像往常一样,没有人关心UTF-16代理对。请参阅以下内容:实际使用中最常见的非BMP Unicode字符是什么?甚至org.apache.commons / commons-lang3的作者

您可以在此示例中看到正确的代码和通常的代码之间的区别:

public static void main(String[] args) {
    //string with FACE WITH TEARS OF JOY symbol
    String s = "abcdafghi\uD83D\uDE02cdefg";
    int maxWidth = 10;
    System.out.println(s);
    //do not care about UTF-16 surrogate pairs
    System.out.println(s.substring(0, Math.min(s.length(), maxWidth)));
    //correctly process UTF-16 surrogate pairs
    if(s.length()>maxWidth){
        int correctedMaxWidth = (Character.isLowSurrogate(s.charAt(maxWidth)))&&maxWidth>0 ? maxWidth-1 : maxWidth;
        System.out.println(s.substring(0, Math.min(s.length(), correctedMaxWidth)));
    }
}

1
在Apache Commons的jira中发现了该错误:issue.apache.org/jira/browse/LANG-1343
Ryan Quinn

10

s = s.length() > 10 ? s.substring(0, 9) : s;


16
子字符串的第二个参数是互斥的,因此此答案将字符串修剪为9个字符。
emulcahy 2013年

8

或者,如果手边没有StringUtils,则可以使用此方法:

public static String abbreviateString(String input, int maxLength) {
    if (input.length() <= maxLength) 
        return input;
    else 
        return input.substring(0, maxLength-2) + "..";
}

您不在乎测试代码,对吗?没用 试试这个System.out.println(abbreviateString("ABC\ud83d\udc3bDEF", 6));
T3rm1

@ T3rm1您总是可以对5岁的代码片段进行改进,以涵盖您的用例,或者向提出问题的人添加更有用的答案。
MVojtkovszky

4

以防万一,您正在寻找一种修整并保留字符串的最后10个字符的方法。

s = s.substring(Math.max(s.length(),10) - 10);

3

使用Kotlin,它很简单:

yourString.take(10)

返回包含此字符串前n个字符的字符串,如果此字符串较短,则返回整个字符串。

文献资料


1

tl; dr

截断时,您似乎在最后要求省略号)。这是处理输入字符串的一种方法。

String input = "abcdefghijkl";
String output = ( input.length () > 10 ) ? input.substring ( 0 , 10 - 1 ).concat ( "…" ) : input;

参见IdeOne.com实时运行代码。

abcdefghi ...

三元运算符

我们可以通过使用三元运算符来制作单线

String input = "abcdefghijkl" ;

String output = 
    ( input.length() > 10 )          // If too long…
    ?                                
    input     
    .substring( 0 , 10 - 1 )         // Take just the first part, adjusting by 1 to replace that last character with an ellipsis.
    .concat( "…" )                   // Add the ellipsis character.
    :                                // Or, if not too long…
    input                            // Just return original string.
;

参见IdeOne.com实时运行代码。

abcdefghi ...

Java流

从Java 9及更高版本开始,Java Streams工具使这一点变得有趣。有趣,但可能不是最佳方法。

我们使用代码点而不是char值。该char类型是旧的,并且限于所有可能的Unicode字符的子集

String input = "abcdefghijkl" ;
int limit = 10 ;
String output =
        input
                .codePoints()
                .limit( limit )
                .collect(                                    // Collect the results of processing each code point.
                        StringBuilder::new,                  // Supplier<R> supplier
                        StringBuilder::appendCodePoint,      // ObjIntConsumer<R> accumulator
                        StringBuilder::append                // BiConsumer<R,​R> combiner
                )
                .toString()
        ;

如果我们有多余的字符被截断,请用省略号替换最后一个字符 。

if ( input.length () > limit )
{
    output = output.substring ( 0 , output.length () - 1 ) + "…";
}

如果我能想到一种将流线与“如果超出限制,则省略号”部分放在一起的方法。


不会。很明显,如果字符串的长度达到或超过11,他想修剪它的长度。您必须正在开发新的AI系统
JD333 '19

1
@ JD333您的评论使我无所适从。我在这里显示的截断长度为10,包括省略号。
罗勒·布尔克

0
str==null ? str : str.substring(0, Math.min(str.length(), 10))

要么,

str==null ? "" : str.substring(0, Math.min(str.length(), 10))

与null一起使用。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.