このような問題が発生したときは、Perlスクリプトを使用して、次のようなコードを使用してデータが有効なUTF-8に変換されるようにしました。
use Encode;
binmode(STDOUT, ":utf8");
while (<>) {
print Encode::decode('UTF-8', $_);
}
このスクリプトは、stdin
でUTF-8を使用します(破損している可能性があります)。 有効なUTF-8をstdout
に再印刷します 。無効な文字は�
に置き換えられます (U+FFFD
、ユニコード置換文字
。
このスクリプトを適切な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: Пр?вет
}
}