web-dev-qa-db-ja.com

文字列から空白をトリムする方法は?

私はJ2MEアプリケーション用にこの関数を書いているので、より高度な/モダンなJavaクラスを利用できません。これでJava.lang.ArrayIndexOutOfBoundsExceptionを取得しています。 、明らかにnewChars配列を初期化した方法が気に入らないか、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();
}
26
user458442

先頭および末尾の空白を削除する簡単な方法は、 String.trim() を呼び出すことです。 (先頭と末尾のすべての空白ではなく)先頭と末尾のスペースだけをトリムしたい場合、これを行うことができる StringUtils.strip(String, String) というApache commonsメソッドがあります。 2番目の引数として_" "_を指定して呼び出します。

試みたコードには多くのバグがあり、根本的に非効率的です。本当にこれを自分で実装したい場合は、次のようにする必要があります。

  1. 先頭のスペース文字を数えます
  2. 末尾のスペース文字を数えます
  3. いずれかのカウントがゼロ以外の場合、String.substring(from, end)を呼び出して、保持する文字を含む新しい文字列を作成します。

このアプローチは、文字のコピーを回避します1


1-実際、それはStringの実装に依存します。一部の実装ではコピーが行われず、他の実装では単一のコピーが作成されます。ただし、どちらもアプローチの改善であり、これには最低2つのコピーが必要であり、トリミングする文字がある場合はさらに多くなります。

37
Stephen C

String.trim()は非常に古く、少なくともJava 1.3。これはありませんか?

14
Tony Ennis

Apache StringUtils.strip は、(スペースだけでなく)予想されるすべての空白文字で動作するベストアンサーです。 ここからダウンロードできます

関連するコードは次のとおりです このソースファイルからリッピング 必要に応じて独自のクラスに実装しますが、実際には、StringUtilsをダウンロードして使用するだけで、より大きな価値を得ることができます! StringUtils.stripStartを使用して、Java文字列から先頭の文字をトリミングすることもできます。

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 (isEmpty(str)) {
        return str;
    }
    str = stripStart(str, stripChars);
    return stripEnd(str, stripChars);
}
4
Brad Parks

JDK/11では、String.stripこの文字列を値とする文字列を返すAPI。先頭および末尾の空白はすべて削除されます。同じためのjavadocは次のとおりです。

/**
 * 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()

これらのサンプルケースは次のとおりです。

System.out.println("".strip());
System.out.println("  both  ".strip());
System.out.println("  leading".strip());
System.out.println("trailing  ".strip());
3
Naman

まず、他の人がString.trim()について言ったこと。本当に、車輪を再発明しないでください。

しかし、記録の場合、コードの問題は、Java配列はサイズ変更できないことです。ターゲット配列を最初にセットアップするとき、サイズ0配列として作成します。 System.arraycopyスタッフにlen - 1文字があります。それはうまくいきません。動作させたい場合は、配列を次のように設定する必要があります。

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

しかし、それは驚くほど非効率的で、ループを通るたびに新しい配列を再割り当てしてコピーします。 Stephen Cが言及した3つのステップを使用し、最後にsubstringを付けます。

3
Daniel Martin

String.trim()メソッドを使用したくない場合は、以下のように実装できます。ロジックは、スペース、タブ、その他の特殊文字などのさまざまなシナリオを処理します。

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              "));

}
1
san242

Guava CharMatcher を使用できます。

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

注:空白はすべてBMPに含まれているため、これは機能します。

0
sffc

コピー先の配列newCharsは、コピーされた値を保持するのに十分な大きさではありません。コピーするデータの長さ(つまり、長さ-1)に初期化する必要があります。

0