【问题标题】:How to remove this non-standard unicode character? [duplicate]如何删除这个非标准的 unicode 字符? [复制]
【发布时间】:2017-11-07 00:46:08
【问题描述】:

我有一个函数“remove4BytesUTF8Char()”来删除社交媒体中出现的一些独特字符,但它不起作用。我可以删除很多其他字符,但不能删除这个。如何从我的字符串中专门摆脱这个?

        String str = "very good\uE056 flavor";
        System.out.println("str before remove: " + str);
        str = UTF8Utils.remove4BytesUTF8Char(str);
        System.out.println("str after remove " + str);

输出如下:

str before remove: very good flavor
str after remove very good flavor

编辑:

public static String remove4BytesUTF8Char(String s) {
        byte[] bytes = s.getBytes();
        byte[] removedBytes = new byte[bytes.length];
        int index = 0;

        String hex;
        String firstChar;
        for (int i = 0; i < bytes.length; ) {
            hex = UTF8Utils.byteToHex(bytes[i]);

            if (hex.length() < 2) {
                System.out.println("fail to check whether contains 4 bytes char(1 byte hex char too short), default return false.");
                // todo, throw exception for this case
                return null;
            }

            firstChar = hex.substring(0, 1);

            if (byteMap.get(firstChar) == null) {
                System.out.println("fail to check whether contains 4 bytes char(no firstchar mapping), default return false.");
                // todo, throw exception for this case
                return null;
            }

            if (firstChar.equals("f")) {
                for (int j = 0; j < byteMap.get(firstChar); j++) {
                    i++;
                }
                continue;
            }

            for (int j = 0; j < byteMap.get(firstChar); j++) {
                removedBytes[index++] = bytes[i++];
            }
        }

        return new String(Arrays.copyOfRange(removedBytes, 0, index));
    }

【问题讨论】:

  • 你已经看过this了吗?
  • 你还没有发布你的函数 remove4BytesUTF8Char。如果没有有问题的代码,我们将无能为力。
  • “嗨,机械师乔。我的车坏了,所以我把它留在家里,然后骑着自行车来这里。请你看看我的自行车,告诉我我的车出了什么问题吗? "
  • @ErwinBolwidt,我添加了我正在使用的功能。
  • 注意: s.getBytes() 在 Windows 上不会返回 UTF-8 字节。

标签: java unicode


【解决方案1】:

您可以将String 视为chars 的数组,然后查看每个char 是否大于127,因为那是largest value for ascii,所以任何更高的都将是utf8 的一部分

public static void main(String...args){
    String str = "very good\uE056 flavor";
    System.out.println(str);
    System.out.println(removeUTF8(str));
}

public static String removeUTF8(String s){
    for(int i = 0; i < s.length(); i++){
        char targetChar = s.charAt(i);
        if(targetChar > 127){
            s = s.replaceAll(Character.toString(targetChar), "");
        }
    }
    return s;
}

【讨论】:

    【解决方案2】:

    所有 char、Character 和 String 都使用 Unicode 的 UTF-16 编码。每个代码点都以一个或两个代码单元 (char) 进行编码。两个 >= U+10000。 Clause D91

    UTF-8 是 Unicode 的另一种编码。每个代码点都以一个、两个、三个或四个代码单元编码(序列化时为byte)。四个 >= U+10000。 Table 3-7

    因此,如果您想过滤掉 UTF-8 用 4 个字节编码的代码点,这与过滤掉 UTF-16 用 2 个字符编码的代码点是一样的。

    现在,UTF-16 在 2 个字符中编码的任何代码点的 2 个字符始终在“\uD800”到“\uDFFF”的范围内。 (它们对应于为防止混淆而保留的surrogate codepoints。)

    好的,这就是您的 remove4BytesUTF8Char 函数要处理的内容。但是,'\uE056' 实际上不是 UTF-8 编码为 4 个字节的 Unicode 代码点的 UTF-16 代码单元。它在 Unicode 的 Private Use Area 块中(在左框中向下滚动):U+E000 到 U+F8FF('\uE000" 到 '\uF8FF')。因此,您必须单独过滤掉它们。

    String input = "very good\uE056 flavor ?";
    System.out.println(input);
    String output = input.chars() // IntStream of UTF-16 code units
        .filter(c -> !Character.isSurrogate((char)c) 
                     && Character.getType((char)c) != Character.PRIVATE_USE)
        .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)
        .toString(); 
    System.out.println(output);
    

    【讨论】:

      猜你喜欢
      • 2017-07-30
      • 2015-04-23
      • 2013-09-25
      • 2013-11-25
      • 2018-05-16
      • 1970-01-01
      • 1970-01-01
      • 2019-06-03
      • 1970-01-01
      相关资源
      最近更新 更多