情况: 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,这是不方便的。 希望有人有更好的主意吗?
答案 0 :(得分:0)
据我所知,iconv命令基于C iconv函数: http://www.gnu.org/software/libiconv/documentation/libiconv-1.11/iconv.3.html
iconv函数返回a中转换的字符数 这次通话期间不可逆转的方式;可逆转换不是 计数。如果出现错误,则设置errno并返回(size_t)( - 1)。
因此您可以尝试反向转换,但根据文档,结果取决于第一次转换的返回代码。当然你可以尝试二进制替换无效字符。