2

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.

4
  • 1
    If you want to “rather keep it core Java”, you should consider that there is no trace method in the core Java logger and {} is not supported by the standard formatter. Commented Jan 27, 2017 at 11:36
  • Our team standardised on SLF4J but I'd rather not leverage it. Commented Jan 27, 2017 at 11:41
  • I see what you are saying. I'll edit out the SLF4J {} in the question. Commented Jan 27, 2017 at 11:46
  • You should do that in the log config, so it's global Commented Jan 27, 2017 at 12:08

3 Answers 3

2

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:

Sign up to request clarification or add additional context in comments.

2 Comments

my corporate platform is blocking something on ideone but it seems that your code logs "" when the content is null, instead of "RESPONSE: ". Putting the length limit in a constant -> +1
No, that code will throw an exception if content is null. You have to change responseContent.length()<=LIMIT to responseContent==null || responseContent.length()<=LIMIT to fix that.
2

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.

1 Comment

Your last sentence is exactly the reason why I don't think this should be the accepted answer. Otherwise +1
0

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()); } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.