MySQL将latin1转换为utf8,cp1252 0x80-0x9F错误

时间:2014-10-16 20:58:09

标签: mysql utf-8 iconv latin1 cp1252

情况: latin1数据库已作为latin1转储,通过iconv转换为utf8并恢复为utf8_unicode_ci。

似乎每次转换都很顺利,除了来自cp1252的0x80-0x9F。我没有完全理解mysql将这些字符翻译成unicode的意思:mysql

  

latin1是默认字符集。 MySQL的latin1与Windows cp1252字符集相同。这意味着它与官方ISO 8859-1或IANA(互联网号码分配机构)latin1相同,除了IANA latin1将0x80和0x9f之间的代码点视为“未定义”,而cp1252,因此MySQL的latin1,分配字符对于那些职位。例如,0x80是欧元符号。对于cp1252中的“未定义”条目,MySQL将0x81转换为Unicode 0x0081,0x8d至0x008d,0x8f至0x008f,0x90至0x0090以及0x9d至0x009d。

我的表格显示为例如€0xC280而不是€0x80。所以我想我通过

误导了转换
iconv -f latin1 -t utf8

相反,我应该通过

转换
iconv -f cp1252 -t utf-8

正如我的测试显示的那样。因为第二行正在做好工作。

所以问题是,如果可以纠正那些坏字符,还是我必须转储整个数据库?

编辑: 是否可以转储错误的数据库并通过

进行转换
  --default-character-set=utf8
  iconv -c -f utf-8 -t latin1
  iconv -f latin1 -t utf-8 

然后再插入数据库? iconv -c会帮助我,还是会丢失信息?

EDIT2: 似乎可以使用以下方法逐个替换损坏的字符:

update history set note = replace(note,unhex('C280'),unhex('E282AC'));

这将成功地用正确的3byte utf8替换错误的2byte glibberish。 当然,必须为每个varchar / text列以及范围中的每个损坏的char执行此操作 0x80-0x9F,这是不方便的。 希望有人有更好的主意吗?

1 个答案:

答案 0 :(得分:0)

据我所知,iconv命令基于C iconv函数: http://www.gnu.org/software/libiconv/documentation/libiconv-1.11/iconv.3.html

  

iconv函数返回a中转换的字符数   这次通话期间不可逆转的方式;可逆转换不是   计数。如果出现错误,则设置errno并返回(size_t)( - 1)。

因此您可以尝试反向转换,但根据文档,结果取决于第一次转换的返回代码。当然你可以尝试二进制替换无效字符。