当我遇到这样的问题时,我使用Perl脚本来确保通过使用这样的代码将数据转换为有效的UTF-8:
use Encode;
binmode(STDOUT, ":utf8");
while (<>) {
print Encode::decode('UTF-8', $_);
}
此脚本采用(可能已损坏)UTF-8,并将有效的 UTF-8 重新打印到 。无效字符将替换为 (,Unicode 替换字符)。stdin
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: Пр?вет
}
}