Lorsque j'ai eu un problème comme celui-ci, j'ai utilisé le script Perl pour m'assurer que les données sont converties en UTF-8 valide en utilisant un code comme celui-ci :
use Encode;
binmode(STDOUT, ":utf8");
while (<>) {
print Encode::decode('UTF-8', $_);
}
Ce script prend (éventuellement corrompu) UTF-8 sur stdin
et réimprime l'UTF-8 valide sur stdout
. Les caractères invalides sont remplacés par �
(U+FFFD
, Caractère de remplacement Unicode
).
Si vous exécutez ce script sur une bonne entrée UTF-8, la sortie doit être identique à l'entrée.
Si vous avez des données dans la base de données, il est logique d'utiliser DBI pour analyser votre ou vos tables et nettoyer toutes les données en utilisant cette approche pour vous assurer que tout est valide UTF-8.
Il s'agit de la version Perl à une ligne de ce même script :
perl -MEncode -e "binmode STDOUT,':utf8';while(<>){print Encode::decode 'UTF-8',\$_}" < bad.txt > good.txt
EDIT :ajout d'une solution Java uniquement .
Voici un exemple de comment procéder en 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: Пр?вет
}
}