Java 如何删除MySQL中不适合utf8编码的坏字符?
我有肮脏的数据。有时它包含像这样的字符。我使用这些数据进行如下查询Java 如何删除MySQL中不适合utf8编码的坏字符?,java,mysql,unicode,utf-8,Java,Mysql,Unicode,Utf 8,我有肮脏的数据。有时它包含像这样的字符。我使用这些数据进行如下查询 WHERE a.address IN ('mydatahere') 对于这个角色,我得到了 org.hibernate.exception.genericjdbception:为“IN”操作非法混合排序规则(utf8\u-bin,隐式),(utf8mb4\u-general\u-ci,可强制),(utf8mb4\u-general\u-ci,可强制) 我怎样才能过滤掉这样的字符?我使用Java 谢谢。当我遇到这样的问题时,我使
WHERE a.address IN ('mydatahere')
对于这个角色,我得到了
org.hibernate.exception.genericjdbception:为“IN”操作非法混合排序规则(utf8\u-bin,隐式),(utf8mb4\u-general\u-ci,可强制),(utf8mb4\u-general\u-ci,可强制)
我怎样才能过滤掉这样的字符?我使用Java
谢谢。当我遇到这样的问题时,我使用Perl脚本确保数据通过以下代码转换为有效的UTF-8:
use Encode;
binmode(STDOUT, ":utf8");
while (<>) {
print Encode::decode('UTF-8', $_);
}
编辑:添加了纯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 = "May be this will help someone as it helped me.
public static String removeBadChars(String s) {
if (s == null) return null;
StringBuilder sb = new StringBuilder();
for(int i=0;i<s.length();i++){
if (Character.isHighSurrogate(s.charAt(i))) continue;
sb.append(s.charAt(i));
}
return sb.toString();
}
String str=“可能这会像帮助我一样帮助别人
String label = "look into my eyes 〠.〠";
Charset charset = Charset.forName("UTF-8");
label = charset.decode(charset.encode(label)).toString();
System.out.println(label);
公共静态字符串removeBadChars(字符串s){
如果(s==null)返回null;
StringBuilder sb=新的StringBuilder();
对于(int i=0;i,您可以对其进行编码,然后从UTF-8对其进行解码:
look into my eyes ?.?
输出:
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
, ""));
}
编辑:我认为这可能只适用于Java 6。一旦在Java机器上将字节数组转换为字符串,就会得到(在大多数机器上默认情况下)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(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]));
}
String[]value={“\\xF0\\x9F\\x98\\x95”、“\\xF0\\x9F\\x91\\x8C”、“/*”、“看着我的眼睛”、“fkdjsf ksdjfslk”、“\\xF0\\x80\\x80\\x80”、“\\xF0\\x9F\\x98\\x95 aa”、“Ok”;
对于(int i=0;i
或者,如果要验证某些字符串是否包含非utf8字符,则可以使用Pattern.matches,如:
$str = preg_replace('/[[:^print:]]/', '', $str);
String[]value={“\\xF0\\x9F\\x98\\x95”、“\\xF0\\x9F\\x91\\x8C”、“/*”、“看着我的眼睛”、“fkdjsf ksdjfslk”、“\\xF0\\x80\\x80\\x80”、“\\xF0\\x9F\\x98\\x95 aa”、“Ok”;
对于(int i=0;i
要使整个web应用程序与UTF8兼容,请阅读此处:
.
您可以检查您的模式。
在PHP中也是如此。在PHP中,我通过只允许可打印数据来实现这一点。这确实有助于清理数据库中的数据。
不过,这是预处理的,有时你没有那种奢侈
抱歉,我需要java解决方案。您需要一个具有相同替换行为的CharsetEncoder,首先获取输入字符串的字节,然后再将其解码回字符串。在本例中,您需要将ByteBuffer替换为源代码中的实际字节流-是文本文件还是SQL列。本例的要点是如何确保您的UTF-8流绝对符合UTF-8。这取决于您如何将这些数据准确地输入到ByteBuffer
或ByteArrayInputStream
中。请注意,如果您需要读卡器,而不是像Java 7那样直接处理缓冲区,可以接受预先配置的CharsetDecoder
,如中所示。为什么Java解决方案n不使用?而不是unicode替换字符?更糟糕的是,所有文档都指示默认替换字符为\uFFFD…可能是错误?(注意,这将删除所有代理项的使用,而不仅仅是无效序列。)@bobince是的,我想到的是MySQL,afaik在BMP以外的字符方面有问题。啊,是的-你必须使用utfmb4来存储星体平面,这是相对较新的(好吧,除非你只是将所有内容转储到二进制字符串中或使用误导性编码,这样你就不会得到Unicode感知字符串排序的好处。)dc00不是紧跟在dbff之后吗?为什么不能是“([\\ud800-\\udfff])您想删除那些IsLowUrrogate()
的字符串。如果您的字符串有一个有效的>BMP字符,我想这会使字符串损坏。您能解释一下“由于大写字母而被注释掉”的原因吗“嗯,您刚刚删除了完全有效的Unicode字符”〠.〠”使用这个方法。问题是如何只替换无效字符,而不是全部。刚刚测试过,它提供了看在眼里〠。〠
输出,这是正确的,因为该代码不应该导致Unicode字符丢失,除非您对Java源文件使用ASCII。
$str = preg_replace('/[[:^print:]]/', '', $str);