How to trim the whitespace from a string? [duplicate]
Asked Answered
S

8

30

I am writing this function for a J2ME application, so I don't have some of the more advanced / modern Java classes available to me. I am getting java.lang.ArrayIndexOutOfBoundsException on this. So, apparently either it doesn't like the way I've initialized the newChars array, or I'm not doing something correctly when calling System.arraycopy.

/*
 * remove any leading and trailing spaces
 */
public static String trim(String str) {
    char[] chars = str.toCharArray();
    int len = chars.length;
    // leading
    while ( (len > 0 ) && ( chars[0] == ' ' ) ) {
        char[] newChars = new char[] {}; // initialize empty array
        System.arraycopy(chars, 1, newChars, 0, len - 1);
        chars = newChars;
        len = chars.length;
    }
    // TODO: trailing
    return chars.toString();
}
Sonya answered 26/9, 2010 at 0:31 Comment(1)
As pointed out, there is a String.trim() method that I missed. However, I thought I'd add what I discovered in the meantime, since I'm a java noob and this might be helpful to others. From the docs for System.arraycopy(): "... an IndexOutOfBoundsException is thrown [if] ... destPos+length is greater than dest.length, the length of the destination array." iow, I could fix my code by initializing my temp array like this: "char[] newChars = new char[len - 1];"Sonya
S
42

The simple way to trim leading and trailing whitespace is to call String.trim(). With Java 11 and later, you can also use String.strip() which uses a different interpretation of what "white space" means1.

If you just want to trim just leading and trailing spaces (rather than all leading and trailing whitespace), there is an Apache commons method called StringUtils.strip(String, String) that can do this; call it with " " as the 2nd argument.

Your attempted code has a number of bugs, and is fundamentally inefficient. If you really want to implement this yourself, then you should:

  1. count the leading space characters
  2. count the trailing space characters
  3. if either count is non-zero, call String.substring(from, end) to create a new string containing the characters you want to keep.

This approach avoids copying any characters2.


1 - The different meanings are explained in the respective javadocs. Alternatively, read the answers to Difference between String trim() and strip() methods in Java 11.

2 - Actually, that depends on the implementation of String. For some implementations there will be no copying, for others a single copy is made. But either is an improvement on your approach, which entails a minimum of 2 copies, and more if there are any characters to trim.

Snapp answered 26/9, 2010 at 0:35 Comment(0)
W
14

String.trim() is very old, at least to java 1.3. You don't have this?

Windom answered 26/9, 2010 at 0:34 Comment(2)
Actually, yes - I somehow missed it when looking for the solution. :/ Many thanks.Sonya
IIRC trim() was in Java 1.1Snapp
D
4

Apache StringUtils.strip is the best answer here that works with all expected white space characters (not just space), and can be downloaded here:

Here's the relevant code ripped from this source file to implement it in your own class if you wanted, but really, just download and use StringUtils to get more bang for your buck! Note that you can use StringUtils.stripStart to trim any leading character from a java string as well.

public static final int INDEX_NOT_FOUND = -1

public static String strip(final String str) {
    return strip(str, null);
}

public static String stripStart(final String str, final String stripChars) {
    int strLen;
    if (str == null || (strLen = str.length()) == 0) {
        return str;
    }
    int start = 0;
    if (stripChars == null) {
        while (start != strLen && Character.isWhitespace(str.charAt(start))) {
            start++;
        }
    } else if (stripChars.isEmpty()) {
        return str;
    } else {
        while (start != strLen && stripChars.indexOf(str.charAt(start)) != INDEX_NOT_FOUND) {
            start++;
        }
    }
    return str.substring(start);
}

public static String stripEnd(final String str, final String stripChars) {
    int end;
    if (str == null || (end = str.length()) == 0) {
        return str;
    }

    if (stripChars == null) {
        while (end != 0 && Character.isWhitespace(str.charAt(end - 1))) {
            end--;
        }
    } else if (stripChars.isEmpty()) {
        return str;
    } else {
        while (end != 0 && stripChars.indexOf(str.charAt(end - 1)) != INDEX_NOT_FOUND) {
            end--;
        }
    }
    return str.substring(0, end);
}

public static String strip(String str, final String stripChars) {
    if (str == null || str.length() == 0) {
        return str;
    }
    str = stripStart(str, stripChars);
    return stripEnd(str, stripChars);
}
Declarer answered 20/3, 2014 at 12:28 Comment(2)
For the sake of blind cut-and-pasters: public static final int INDEX_NOT_FOUND = -1;Bernstein
Whoops! thanks for the tip - i just added it in.Declarer
H
3

First of all, what others said about String.trim(). Really, don't reinvent the wheel.

But for the record, what's going wrong with your code is that Java arrays aren't resizeable. When you initially set up your target array, you create it as a size 0 array. You then tell System.arraycopy to stuff len - 1 characters in there. That's not going to work. If you wanted it to work, you'd need to set up the array as:

char[] newChars = new char[len - 1];

But that's amazingly inefficient, reallocating and copying a new array each time through the loop. Use the three steps that Stephen C mentioned, ending with a substring.

Hyperparathyroidism answered 26/9, 2010 at 0:44 Comment(0)
C
3

With JDK/11, now you can make use of the String.strip API to return a string whose value is this string, with all leading and trailing whitespace removed. The javadoc for the same is :

/**
 * Returns a string whose value is this string, with all leading
 * and trailing {@link Character#isWhitespace(int) white space}
 * removed.
 * <p>
 * If this {@code String} object represents an empty string,
 * or if all code points in this string are
 * {@link Character#isWhitespace(int) white space}, then an empty string
 * is returned.
 * <p>
 * Otherwise, returns a substring of this string beginning with the first
 * code point that is not a {@link Character#isWhitespace(int) white space}
 * up to and including the last code point that is not a
 * {@link Character#isWhitespace(int) white space}.
 * <p>
 * This method may be used to strip
 * {@link Character#isWhitespace(int) white space} from
 * the beginning and end of a string.
 *
 * @return  a string whose value is this string, with all leading
 *          and trailing white space removed
 *
 * @see Character#isWhitespace(int)
 *
 * @since 11
 */
public String strip()

The sample cases for these could be:--

System.out.println("".strip());
System.out.println("  both  ".strip());
System.out.println("  leading".strip());
System.out.println("trailing  ".strip());
Cullan answered 31/5, 2018 at 19:9 Comment(4)
I switched the duplicates because the other Q&A has many more views (despite being closed) and this Q&A is a debugging question. I think you should post this answer under the other question because more people will see it. (Otherwise some 6/7 people visiting the site won't see the new method.)Ricercar
@Ricercar Okay, sure. Have moved the answerCullan
How is this different from the trim() function?Muhammadan
@Muhammadan #51267082Cullan
B
1

If you don't want to use String.trim() method, then it can be implemented like below. The logic will handle different scenarios like space, tab and other special characters.

public static String trim(String str){
    int i=0;
    int j = str.length();
    char[] charArray = str.toCharArray();
    while((i<j) && charArray[i] <=' '){
        i++;
    }
    while((i<j) && charArray[j-1]<= ' '){
        j--;
    }
    return str.substring(i, j+1);

}

public static void main(String[] args) {
    System.out.println(trim("    abcd ght trip              "));

}
Barrage answered 7/1, 2017 at 22:41 Comment(0)
I
0

The destination array newChars is not large enough to hold the values copied. You need to initialize it to the length of the data you intend to copy (so, length - 1).

Impartible answered 26/9, 2010 at 0:43 Comment(0)
C
0

You can use Guava CharMatcher.

String outputString = CharMatcher.whitespace().trimFrom(inputString);

Note: This works because whitespace is all in the BMP.

Ciliata answered 26/6, 2018 at 2:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.