Adam
Adam

Reputation: 5445

Limiting string length and adding "..." if truncated

Can I limit a string length and add "..." to the end if the string was truncated, without using the

if ... else ...

String responseContent = response.getContent();
if (responseContent == null || responseContent.length() <= 1000) {
    log.finest(String.format("RESPONSE: %s", responseContent));
} else {
    log.finest(String.format("RESPONSE: %.999s ...", responseContent));
}

This is for logging purposes. SLF4j solutions might work, but I'd rather keep it core Java.

Already checked out Limiting the number of characters in a string, and chopping off the rest and related questions.

Upvotes: 2

Views: 2499

Answers (3)

beat
beat

Reputation: 2022

This is not core Java, but if you are using Apache commons lang, you can use StringUtils abbreviate method.

Sample code:

@Test
public void abbrevTest(){
    String longStr = StringUtils.repeat("a", 100);
    String abbreviate = StringUtils.abbreviate(longStr, 50);
    Assert.assertTrue(StringUtils.endsWith(abbreviate, "..."));
    Assert.assertEquals(50, abbreviate.length());
    String shortStr = StringUtils.repeat("a", 10);
    String shortAbbrev = StringUtils.abbreviate(shortStr, 50);
    Assert.assertTrue(StringUtils.endsWith(shortAbbrev, "a"));
    Assert.assertEquals(10, shortAbbrev.length());
}

Upvotes: 0

Holger
Holger

Reputation: 298113

It’s not clear when the SLF4J API will catch up, but the Java 8 core API allows to defer any potentially expensive calculation to the point after the logging level has been checked, so it does not happen if the particular level is not loggable:

import java.util.logging.Logger;

public class LogAbbr {
    final static int LIMIT = 15;
    public static void main(String[] args) {
        Logger log=Logger.getAnonymousLogger();
        String[] examples={"short string", "rather long string"};
        for(String responseContent: examples) {
            log.info(() -> String.format("RESPONSE: %."+LIMIT+"s%s",
                responseContent, responseContent.length()<=LIMIT? "": "..."));
        }
    }
}

Note that when LIMIT is a compile-time constant, "RESPONSE: %."+LIMIT+"s%s" is a compile-time constant too, hence, there is no need to manually inline the number, so using a named constant ensures consistency between the formatting string and the conditional.

Demo on Ideone:

Jan 27, 2017 11:53:20 AM Ideone main
INFO: RESPONSE: short string
Jan 27, 2017 11:53:20 AM Ideone main
INFO: RESPONSE: rather long str...

The following program demonstrates that the calculation does not happen, once the log level forbids it:

Logger log=Logger.getAnonymousLogger();
String[] examples={"short string", "rather long string"};
for(String responseContent: examples) {
    log.info(() -> {
        System.out.println("Potentially expensive operation with "+responseContent);
        return responseContent;
    });
    log.setLevel(Level.SEVERE);
}

Demo on Ideone:

Upvotes: 2

Stephen C
Stephen C

Reputation: 718708

Here's one way

public String shorten(String s, int max) {
    if (s != null && s.length() > max) {
        s = s.substring(0, max - 3) + "...";
    return s;
}

Note that this can break if the string that you are shortening includes characters that are not in the BMP.

(I wouldn't normally do a null test there, but your use-case requires it.)

Then ...

log.trace("RESPONSE: {}", shorten(responseContent, 1000);

... except that you should now guard the trace call to avoid unnecessary calls to shorten.

Upvotes: 2

Related Questions