JDK的String.trim()方法相当简单,只能删除ASCII控制字符。
Apache Commons的StringUtils.strip()略微好一些,但它使用了JDK的Character.isWhitespace(), 这个方法不能将非间断空格识别为空白字符。
那么,在Java中修剪字符串的最完整、Unicode兼容、安全和正确的方法是什么呢?
顺便提一下,除了commons-lang
,还有比这更好的库可以用来处理这种情况吗?
JDK的String.trim()方法相当简单,只能删除ASCII控制字符。
Apache Commons的StringUtils.strip()略微好一些,但它使用了JDK的Character.isWhitespace(), 这个方法不能将非间断空格识别为空白字符。
那么,在Java中修剪字符串的最完整、Unicode兼容、安全和正确的方法是什么呢?
顺便提一下,除了commons-lang
,还有比这更好的库可以用来处理这种情况吗?
谷歌最近提供了guava-libraries。它可能有你正在寻找的东西:
CharMatcher.inRange('\0', ' ').trimFrom(str)
等价于String.trim(),但您可以自定义要修剪的内容,请参阅JavaDoc。
例如,它具有自己的 WHITESPACE 定义,与 JDK 不同,并根据最新的Unicode标准进行定义,因此您需要的内容可以编写为:
CharMatcher.WHITESPACE.trimFrom(str)
我发帖后才看到这个消息:谷歌刚发布了一个名为Guava的Java核心工具库。
虽然我还没有尝试过,但据我所知,它完全符合Unicode标准:
String s = " \t testing \u00a0"
s = CharMatcher.WHITESPACE.trimFrom(s);
很难定义什么构成了空白符。有时我使用不间断空格来确保它不会被剥离。因此,很难找到一个完全符合您要求的库。
如果想要去除每个空白符,我会使用自己的trim()函数。以下是我用来检查空白符的函数:
public static boolean isWhitespace (int ch)
{
if (ch == ' ' || (ch >= 0x9 && ch <= 0xD))
return true;
if (ch < 0x85) // short-circuit optimization.
return false;
if (ch == 0x85 || ch == 0xA0 || ch == 0x1680 || ch == 0x180E)
return true;
if (ch < 0x2000 || ch > 0x3000)
return false;
return ch <= 0x200A || ch == 0x2028 || ch == 0x2029
|| ch == 0x202F || ch == 0x205F || ch == 0x3000;
}
CharMatcher.WHITESPACE
。在处理Unicode时,String#trim()
效果非常糟糕。 - Matt Ball我一直觉得trim
在几乎所有场景下都表现良好。
然而,如果你真的想包含更多字符,你可以编辑commons-lang
中的strip
方法,不仅要测试Character.isWhitespace
,还要测试Character.isSpaceChar
,这似乎是缺失的。也就是说,在stripStart
和stripEnd
中分别添加以下行:
while ((start != strLen) && Character.isWhitespace(str.charAt(start)))
while ((end != 0) && Character.isWhitespace(str.charAt(end - 1)))
我对 Java 的 trim() 方法做了一些小修改,现在它支持非 ASCII 字符。这个方法运行速度比大多数实现都要快。
public static String trimAdvanced(String value) {
Objects.requireNonNull(value);
int strLength = value.length();
int len = value.length();
int st = 0;
char[] val = value.toCharArray();
if (strLength == 0) {
return "";
}
while ((st < len) && (val[st] <= ' ') || (val[st] == '\u00A0')) {
st++;
if (st == strLength) {
break;
}
}
while ((st < len) && (val[len - 1] <= ' ') || (val[len - 1] == '\u00A0')) {
len--;
if (len == 0) {
break;
}
}
return (st > len) ? "" : ((st > 0) || (len < strLength)) ? value.substring(st, len) : value;
}
这个处理Unicode字符,不需要额外的库:
String trimmed = original.replaceAll ("^\\p{IsWhite_Space}+|\\p{IsWhite_Space}+$", "");
String trimmed = original.replaceAll (either (START_BOUNDARY + oneOrMore (WHITESPACE), oneOrMore (WHITESPACE) + END BOUNDARY), "");
并包括非Unicode空格中更相关的内容。
trimAndCollapseFrom
修剪字符串的外部,同时也替换了字符串内部重复的值。 - Basil Bourque