190

I want to trim a string if the length exceeds 10 characters.

Suppose if the string length is 12 (String s="abcdafghijkl"), then the new trimmed string will contain "abcdefgh..".

How can I achieve this?

Hexaholic
  • 3,299
  • 7
  • 30
  • 39
yshak
  • 1,991
  • 2
  • 16
  • 14
  • 6
    possible duplicate of [up to first N characters](http://stackoverflow.com/questions/1583940/up-to-first-n-characters) – Stephen C Dec 14 '11 at 05:14
  • FYI, a [HORIZONTAL ELLIPSIS](https://en.wikipedia.org/wiki/Ellipsis) is a single character, not two or three [FULL STOP](https://en.wikipedia.org/wiki/Full_stop) characters: … – Basil Bourque Aug 01 '19 at 23:39

12 Answers12

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

Using Math.min like this avoids an exception in the case where the string is already shorter than 10.


Notes:

  1. The above does simple trimming. If you actually want to replace the last characters with three dots if the string is too long, use Apache Commons StringUtils.abbreviate; see @H6's solution. If you want to use the Unicode horizontal ellipsis character, see @Basil's solution.

  2. For typical implementations of String, s.substring(0, s.length()) will return s rather than allocating a new String.

  3. This may behave incorrectly1 if your String contains Unicode codepoints outside of the BMP; e.g. Emojis. For a (more complicated) solution that works correctly for all Unicode code-points, see @sibnick's solution.


1 - A Unicode codepoint that is not on plane 0 (the BMP) is represented as a "surrogate pair" (i.e. two char values) in the String. By ignoring this, we might trim the string to fewer than 10 code points, or (worse) truncate it in the middle of a surrogate pair. On the other hand, String.length() is not a good measure of Unicode text length, so trimming based on that property may be the wrong thing to do.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • Instead of Math.min can't we do a conditional check and do substring only if string is max then required ? eg: `s = (s.length() > 10) ? s.substring(0,10) : s ;` – rram Feb 14 '19 at 19:47
  • 1
    @rram if you get inside the substring method, you will see, that this behavior is actually done under the hood. – Alexander.Iljushkin Nov 12 '21 at 00:10
163

StringUtils.abbreviate from Apache Commons Lang library could be your friend:

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

Commons Lang3 even allow to set a custom String as replacement marker. With this you can for example set a single character ellipsis.

StringUtils.abbreviate("abcdefg", "\u2026", 6) = "abcde…"
disco crazy
  • 31,313
  • 12
  • 80
  • 83
  • 5
    It could be, but the OP's question does not ask for "ellipsis". – Stephen C Feb 19 '14 at 01:00
  • 12
    @StephenC - The question show 8 characters followed by 2 dots, given a length limit of 10, which is a lot like an ellipsis (just 2 dots rather than 3). Its also likely that many of the people who find this question would consider an ellipsis to be useful. – ToolmakerSteve Aug 20 '14 at 05:29
  • 15
    ...and if you don't want the ellipsis, then StringUtils.left() can help you. – Superole Oct 15 '15 at 09:04
  • 2
    FYI, a [HORIZONTAL ELLIPSIS](https://en.wikipedia.org/wiki/Ellipsis) is a single character, not three [FULL STOP](https://en.wikipedia.org/wiki/Full_stop) characters: … – Basil Bourque Aug 01 '19 at 23:39
81

There is a Apache Commons StringUtils function which does this.

s = StringUtils.left(s, 10)

If len characters are not available, or the String is null, the String will be returned without an exception. An empty String is returned if len is negative.

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

Courtesy:Steeve McCauley

rds
  • 26,253
  • 19
  • 107
  • 134
Whimsical
  • 5,985
  • 1
  • 31
  • 39
30

As usual nobody cares about UTF-16 surrogate pairs. See about them: What are the most common non-BMP Unicode characters in actual use? Even authors of org.apache.commons/commons-lang3

You can see difference between correct code and usual code in this sample:

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)));
    }
}
Community
  • 1
  • 1
sibnick
  • 3,995
  • 20
  • 20
10

Or you can just use this method in case you don't have StringUtils on hand:

public static String abbreviateString(String input, int maxLength) {
    if (input.length() <= maxLength) 
        return input;
    else 
        return input.substring(0, maxLength-2) + "..";
}
MVojtkovszky
  • 519
  • 4
  • 11
  • Your code didn't work for me. Try this `System.out.println(abbreviateString("ABC\ud83d\udc3bDEF", 6));` – T3rm1 Jul 28 '20 at 06:38
9

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

shift66
  • 11,760
  • 13
  • 50
  • 83
5

Just in case you are looking for a way to trim and keep the LAST 10 characters of a string.

s = s.substring(Math.max(s.length(),10) - 10);
pushkin
  • 9,575
  • 15
  • 51
  • 95
rekotc
  • 595
  • 1
  • 10
  • 21
5

tl;dr

You seem to be asking for an ellipsis () character in the last place, when truncating. Here is a one-liner to manipulate your input string.

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

See this code run live at IdeOne.com.

abcdefghi…

Ternary operator

We can make a one-liner by using the ternary operator.

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.
;

See this code run live at IdeOne.com.

abcdefghi…

Java streams

The Java Streams facility makes this interesting, as of Java 9 and later. Interesting, but maybe not the best approach.

We use code points rather than char values. The char type is legacy, and is limited to the a subset of all possible Unicode characters.

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 we had excess characters truncated, replace the last character with an ellipsis.

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

If only I could think of a way to put together the stream line with the "if over limit, do ellipsis" part.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
3

The question is asked on Java, but it was back in 2014.
In case you use Kotlin now, it is as simple as:

yourString.take(10)

Returns a string containing the first n characters from this string, or the entire string if this string is shorter.

Documentation

Leo DroidCoder
  • 14,527
  • 4
  • 62
  • 54
  • Note to people looking for Kotlin specific answers. Search for Q&A's in the `[kotlin]` tag, and ask then in the `[kotlin]` tag. – Stephen C Apr 19 '22 at 02:22
1
str==null ? str : str.substring(0, Math.min(str.length(), 10))

or,

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

Works with null.

aceminds
  • 11
  • 3
  • But note that if you are not expecting a `null` you should not do either of these. The best way to deal with (unexpected) nulls is to allow the NPE to occur (ASAP), and then use the bug report to track down and eliminate the cause of the unexpected `null`. If you "defensively" test for nulls without understanding the source, you can end up obscuring the cause of significant bugs. – Stephen C Sep 13 '21 at 02:11
1

A great compact way, without having to use a third party library, would be to use the ternary operator (?:) as described by @BasilBourque:

s = s.length() > 10 ? s.substring(0, 10 - 2).concat("..") : s;

but it might be just as simple to use a "one-line" if-statement:

if (s.length() > 10) s = s.substring(0, 10 - 2) + "..";
Snostorp
  • 544
  • 1
  • 8
  • 14
-1

// this is how you shorten the length of the string with .. // add following method to your class

private String abbreviate(String s){
  if(s.length() <= 10) return s;
  return s.substring(0, 8) + ".." ;
}