ダーティデータがあります。 this のような文字が含まれている場合があります。このデータを使用して、次のようなクエリを作成します
WHERE a.address IN ('mydatahere')
このキャラクターには
org.hibernate.exception.GenericJDBCException:照合の不正な組み合わせ(utf8_bin、IMPLICIT)、(utf8mb4_general_ci、COERCIBLE)、(utf8mb4_general_ci、COERCIBLE)for operation 'IN'
このような文字を除外するにはどうすればよいですか?私はJavaを使用しています。
ありがとう。
このような問題が発生したときは、Perlスクリプトを使用して、次のようなコードを使用してデータが有効なUTF-8に変換されるようにしました。
use Encode;
binmode(STDOUT, ":utf8");
while (<>) {
print Encode::decode('UTF-8', $_);
}
このスクリプトは、stdin
で(おそらく破損している)UTF-8を受け取り、有効なUTF-8をstdout
に再出力します。無効な文字は�
(U+FFFD
、 nicode置換文字 )に置き換えられます。
このスクリプトを適切な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: Пр?вет
}
}
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 ?.?
編集:これはJava 6。
この正規表現を使用して、代理文字をフィルタリングできます。
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マシンでバイト配列を文字列に変換すると、ほとんどのマシンではデフォルトで)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
, ""));
}
または、一部の文字列に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互換にするためには、以下をお読みください。
Java webapps でUTF-8を機能させる方法
バイトエンコーディングと文字列の詳細 。
パターンを確認できます ここ 。
PHP here 。
PHP-では、印刷可能なデータのみを許可することでこれに取り組みます。これは、DBのデータのクリーンアップに非常に役立ちます。
ただし、これは前処理であり、そのような贅沢さがない場合もあります。
$str = preg_replace('/[[:^print:]]/', '', $str);