如何在Java中替换/删除UTF-8字符串中的4(+)字节字符?

因为MySQL 5.1不支持4字节UTF-8序列,所以我需要替换/删除这些字符串中的4字节序列。

我正在寻找一种干净的方法来替换这些角色。

对于这种情况,Apache库正在用问号替换字符,但是当然,ASCII等价物会更好。

NB输入来自外部源(电子邮件名称),此时升级数据库不是解决方案。

我们最终在Java中为此问题实现了以下方法。 Basicaly用更高的代码点替换字符,然后用最后的3字节UTF-8字符替换。

偏移计算是为了确保我们保持unicode代码点。

public static final String LAST_3_BYTE_UTF_CHAR = "\uFFFF"; public static final String REPLACEMENT_CHAR = "\uFFFD"; public static String toValid3ByteUTF8String(String s) { final int length = s.length(); StringBuilder b = new StringBuilder(length); for (int offset = 0; offset < length; ) { final int codepoint = s.codePointAt(offset); // do something with the codepoint if (codepoint > CharUtils.LAST_3_BYTE_UTF_CHAR.codePointAt(0)) { b.append(CharUtils.REPLACEMENT_CHAR); } else { if (Character.isValidCodePoint(codepoint)) { b.appendCodePoint(codepoint); } else { b.append(CharUtils.REPLACEMENT_CHAR); } } offset += Character.charCount(codepoint); } return b.toString(); } 

另一个简单的解决方案是使用正则表达式[^\u0000-\uFFFF] 。 例如在java中:

 text.replaceAll("[^\\u0000-\\uFFFF]", "\uFFFD"); 

5字节utf-8序列以111110xx字节开头,6字节utf-8序列以1111110x字节开头。 需要注意的是,没有1-4字节utf-8序列的后续字节包含大的字节,因为后续字节总是10xxxxxx的forms。

因此,你只需要查看字节,每次看到一个111110xx类型的字节,然后只发出一个’?’ 输出流/数组,同时从输入跳过接下来的4个字节; 6字节序列的模拟。