如何删除不适合MySQL中utf8编码的错误字符?

我有脏数据。 有时它包含这样的字符。 我使用这些数据来进行查询

WHERE a.address IN ('mydatahere') 

对于这个角色,我得到了

org.hibernate.exception.GenericJDBCException:操作’IN’的非法混合排序(utf8_bin,IMPLICIT),(utf8mb4_general_ci,COERCIBLE),(utf8mb4_general_ci,COERCIBLE)

如何过滤掉这样的字符? 我用的是Java。

谢谢。

您可以对UTF-8进行编码然后将其解码:

 String label = "look into my eyes 〠.〠"; Charset charset = Charset.forName("UTF-8"); label = charset.decode(charset.encode(label)).toString(); System.out.println(label); 

输出:

 look into my eyes ?.? 

当我遇到这样的问题时,我使用Perl脚本来确保使用以下代码将数据转换为有效的UTF-8:

 use Encode; binmode(STDOUT, ":utf8"); while (<>) { print Encode::decode('UTF-8', $_); } 

此脚本在stdin上获取(可能已损坏)UTF-8并将有效的UTF-8重新打印到stdout 。 无效字符将替换为 U+FFFD , Unicode替换字符 )。

如果在良好的UTF-8输入上运行此脚本,则输出应与输入相同。

如果数据库中有数据,则使用DBI扫描表并使用此方法清理所有数据以确保所有数据都是有效的UTF-8是有意义的。

这是同一个脚本的Perl单行版本:

 perl -MEncode -e "binmode STDOUT,':utf8';while(<>){print Encode::decode 'UTF-8',\$_}" < bad.txt > good.txt 

编辑:添加了仅Java解决方案

这是一个如何在Java中执行此操作的示例:

 import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.CharacterCodingException; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.nio.charset.CodingErrorAction; public class UtfFix { public static void main(String[] args) throws InterruptedException, CharacterCodingException { CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder(); decoder.onMalformedInput(CodingErrorAction.REPLACE); decoder.onUnmappableCharacter(CodingErrorAction.REPLACE); ByteBuffer bb = ByteBuffer.wrap(new byte[] { (byte) 0xD0, (byte) 0x9F, // 'П' (byte) 0xD1, (byte) 0x80, // 'р' (byte) 0xD0, // corrupted UTF-8, was 'и' (byte) 0xD0, (byte) 0xB2, // 'в' (byte) 0xD0, (byte) 0xB5, // 'е' (byte) 0xD1, (byte) 0x82 // 'т' }); CharBuffer parsed = decoder.decode(bb); System.out.println(parsed); // this prints: Пр?вет } } 

您可以使用此正则表达式过滤代理项字符:

 String str = "𠀀"; //U+20000, represented by 2 chars in java (UTF-16 surrogate pair) str = str.replaceAll( "([\\ud800-\\udbff\\udc00-\\udfff])", ""); System.out.println(str.length()); //0 

在java机器上将字节数组转换为String后,您将获得(默认情况下在大多数机器上)UTF-16编码的字符串。 摆脱非UTF-8字符的正确解决方案是使用以下代码:

 String[] values = {"\\xF0\\x9F\\x98\\x95", "\\xF0\\x9F\\x91\\x8C", "/*", "look into my eyes 〠.〠", "fkdjsf ksdjfslk", "\\xF0\\x80\\x80\\x80", "aa \\xF0\\x9F\\x98\\x95 aa", "Ok"}; for (int i = 0; i < values.length; i++) { System.out.println(values[i].replaceAll( //"[\\\\x00-\\\\x7F]|" + //single-byte sequences 0xxxxxxx - commented because of capitol letters "[\\\\xC0-\\\\xDF][\\\\x80-\\\\xBF]|" + //double-byte sequences 110xxxxx 10xxxxxx "[\\\\xE0-\\\\xEF][\\\\x80-\\\\xBF]{2}|" + //triple-byte sequences 1110xxxx 10xxxxxx * 2 "[\\\\xF0-\\\\xF7][\\\\x80-\\\\xBF]{3}" //quadruple-byte sequence 11110xxx 10xxxxxx * 3 , "")); } 

或者如果你想validation某些字符串是否包含非utf8字符,你可以使用Pattern.matches:

 String[] values = {"\\xF0\\x9F\\x98\\x95", "\\xF0\\x9F\\x91\\x8C", "/*", "look into my eyes 〠.〠", "fkdjsf ksdjfslk", "\\xF0\\x80\\x80\\x80", "aa \\xF0\\x9F\\x98\\x95 aa", "Ok"}; for (int i = 0; i < values.length; i++) { System.out.println(Pattern.matches( ".*(" + //"[\\\\x00-\\\\x7F]|" + //single-byte sequences 0xxxxxxx - commented because of capitol letters "[\\\\xC0-\\\\xDF][\\\\x80-\\\\xBF]|" + //double-byte sequences 110xxxxx 10xxxxxx "[\\\\xE0-\\\\xEF][\\\\x80-\\\\xBF]{2}|" + //triple-byte sequences 1110xxxx 10xxxxxx * 2 "[\\\\xF0-\\\\xF7][\\\\x80-\\\\xBF]{3}" //quadruple-byte sequence 11110xxx 10xxxxxx * 3 + ").*" , values[i])); } 

要使整个Web应用程序兼容UTF8,请在此处阅读:
如何让UTF-8在Java webapps中运行
有关字节编码和字符串的更多信息 。
你可以在这里查看你的模式。
这里的 PHP也一样。

可能这会帮助某人,因为它帮助了我。

 public static String removeBadChars(String s) { if (s == null) return null; StringBuilder sb = new StringBuilder(); for(int i=0;i