从字符串中删除“空”字符

16

我正在使用一个框架,它会不时地返回包含“空”字符的格式不正确的字符串。

例如,“foobar”表示为:[,f,o,o,b,a,r]

第一个字符不是空格(' '),因此System.out.printlin()将返回“foobar”,而不是“ foobar”。然而,该字符串的长度为7而不是6。显然,这使得大多数字符串方法(equals、split、substring等)无用。是否有一种方法可以从字符串中删除空字符?

我尝试像这样构建一个新的字符串:

StringBuilder sb = new StringBuilder();
for (final char character : malformedString.toCharArray()) {
  if (Character.isDefined(character)) {
    sb.append(character);
  }
}
sb.toString();

很不幸,这并不起作用。以下代码也是如此:

StringBuilder sb = new StringBuilder();
for (final Character character : malformedString.toCharArray()) {
  if (character != null) {
    sb.append(character);
  }
}
sb.toString();

我也无法像这样检查空字符:

   if (character == ''){
     //
   }

显然,这个字符串有问题...但我不能改变我正在使用的框架,也不能等待他们修复它(如果是他们框架中的错误)。 我需要处理这个字符串并对其进行清理。

你有什么想法吗?


4
那是什么?尝试写出每个字符的Unicode数值(只需将字符强制转换为整数)。 - Thorbjørn Ravn Andersen
6
可能那是一个U+FEFF字符吗?那么它可能是以UTF-*格式存储的文件的字节顺序标记。 - Joey
10个回答

21

在这种情况下,使用正则表达式来清除字符串中不需要的Unicode字符是一个适当的方式。

String sanitized = dirty.replaceAll("[\uFEFF-\uFFFF]", ""); 

这将用空字符串替换\uFEFF-\uFFFF范围内的所有char

[...]结构称为字符类,例如[aeiou]匹配任何小写元音字母中的一个,[^aeiou]匹配除此之外的任何字符。

你可以选择以下两种方法之一:

  • replaceAll("[blacklist]", "")
  • replaceAll("[^whitelist]", "")

参考资料


16

可能是由\0表示的空字符引起的。您可以通过使用String#trim()来摆脱它。

要确定确切的代码点,请执行以下操作:

for (char c : string.toCharArray()) {
    System.out.printf("U+%04x ", (int) c);
}

然后你可以在这里找到确切的字符。


更新:根据以下更新:

有没有办法只包含一定范围内的有效字符而不是排除 95% 的 UTF8 范围?

您可以通过正则表达式来实现这一点。请参见@polygenelubricants在此处的答案和此答案

另一方面,您也可以直接解决问题,而不是绕过它。要么更新文件以摆脱 BOM 标记——这是一种区分 UTF-8 文件和其他文件的传统方法,现在已经毫无用处,要么使用识别并跳过 BOM 的Reader。请参见此问题


7

使用Denis Tulskiy建议的substring方法非常简单地从字符串中删除UTF-8 BOM。无需循环,只需检查标记的第一个字符,如果需要,就跳过它。

public static String removeUTF8BOM(String s) {
    if (s.startsWith("\uFEFF")) {
        s = s.substring(1);
    }
    return s;
}

我在使用Apache HTTPClient EntityUtil从web服务器读取数据时,需要向我的代码中添加这段内容。尽管该Web服务器未发送空白标记,但它在读取输入流时被吸收了进来。原始文章可在这里找到。

谢谢你指出这个问题,你帮我省了很多时间 :-) - slodeveloper

2
感谢Johannes Rössel。实际上它是'\uFEFF'。
以下代码可行:
 final StringBuilder sb = new StringBuilder();
    for (final char character : body.toCharArray()) {
       if (character != '\uFEFF') {
          sb.append(character);
       }
     }  
 final String sanitzedString = sb.toString();

有没有办法只包括一定范围内的有效字符,而不是排除 95% 的 UTF8 范围?


1
然后,您应该更准确地定义“有效字符”。 - BalusC
这是低效的方法,只需要检查第一个字符是否为FEFF并使用子字符串, String.trim() 将完成其余工作。 - Denis Tulskiy

1

去除左侧或右侧的空格。在空格之前是否有冒号?

更进一步: a =(long)string [0]; 将显示字符代码,您可以使用replace()或substring。


0

你可以尝试使用replace

s.replace("\u200B", "")

或者

s.replace("\uFEFF", "")

Kotlin:

s.filter { it == '\u200B' }

0

这是对我有效的方法:

    StringBuilder sb = new StringBuilder();
    for (char character : myString.toCharArray()) {
        int i = (int) character;
        if (i > 0 && i <= 256) {
            sb.append(character);
        }
    }  
    return sb.toString();

我的 NULL 字符的 int 值大约在 8103 左右。


-1
for (int i = 0; i < s.length(); i++)
    if (s.charAt(i) == ' ') {
        your code....
    }

-1

只需使用 malformedString.trim() 即可解决问题。


3
不,它不相等:"\uFEFFTYPE".trim().equals("\uFEFFTYPE") - Kariem

-3
你可以像这样检查空格:
if (character.equals(' ')){ // }

2
问题已经确定该字符不是空格。 - Nick
问题确实说不是空格;然而,在给出的三个代码示例中,他使用比较运算符来检查字符,如果我没有弄错,你不能使用比较运算符来检查某个特定字符,因为它们检查的是你是否引用了内存中的同一位置而不是字符代码。这只是基于提供的代码的一个有用的建议/选项。 - daiglebagel
我明白你的想法 - 对于一个字符对象,使用equals()是正确的做法。当处理字符时,我倾向于使用char,并且对于char,你可以使用==因为它是一种原始类型。 - Nick

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接