修复损坏的UTF8编码
我正在修复一些不好的UTF8编码的过程。 我目前正在使用PHP 5和MySQL
在我的数据库中,我有几个不好的编码实例,打印如下:?
- 数据库sorting规则是utf8_general_ci
- PHP正在使用一个正确的UTF8头
- 记事本++被设置为使用UTF8没有BOM
- 数据库pipe理在phpMyAdmin中处理
- 不是所有重音字符的情况都被破坏了
我所需要的是某种function,它可以帮助我将ƒƒ®,ƒƒƒ¼¼和其他类似的实例映射到它们正确的带有重音的UTF8字符。
过去我不得不试图“修复”一些UTF8破碎的情况,不幸的是,这并不容易,而且往往是不可能的。
除非你能确定它是如何被破坏的,而且它总是以同样的方式被破坏,否则将很难“消除”破坏。
如果您想尝试撤消损坏,最好的方法是开始编写一些示例代码,在此尝试对mb_convert_encoding()的调用进行多种修改,以查看是否可以find“from”和“to”的组合修复你的数据。 最后,由于所涉及的痛苦程度,最好不要担心修复旧数据,而只是为了解决前进的问题。
但是,在执行此操作之前,您需要确保首先解决导致此问题的所有问题。 你已经提到你的数据库表整理和编辑器设置正确。 但是还有更多的地方需要检查,以确保一切正常UTF-8:
- 确保您的HTML格式为UTF-8:
- header(“Content-Type:text / html; charset = utf-8”);
- 改变你的PHP默认字符集为utf-8:
- ini_set(“default_charset”,“utf-8”);
- 如果你的数据库并不总是用utf-8来说话,那么你可能需要在每个连接的基础上告诉它,以确保它处于utf-8模式,在MySQL中你可以通过发出:
- charset utf8
- 您可能需要告诉您的Web服务器总是试图用UTF8进行对话,在Apache中这个命令是:
- AddDefaultCharset UTF-8
- 最后,您需要始终确保您使用的是正确使用UTF-8的PHP函数。 这意味着始终使用mb_ *样式的“多字节感知”string函数。 这也意味着在调用htmlspecialchars()之类的函数时,在末尾包含相应的“utf-8”字符集参数,以确保它不会错误地编码它们。
如果你错过了整个过程的任何一步,编码可能会发生改变,并出现问题。 一旦进入了utf-8的“槽”,这一切就成了第二天性。 当然,PHP6应该是来自getgo的完全unicode投诉,这将使更多的这更容易(希望)
如果你有双重编码的UTF8字符(各种聪明的引号,破折号,撇号,引号等),你可以在mysql中转储数据,然后读回来修复破坏的编码。
喜欢这个:
mysqldump -h DB_HOST -u DB_USER -p DB_PASSWORD --opt --quote-names \ --skip-set-charset --default-character-set=latin1 DB_NAME > DB_NAME-dump.sql mysql -h DB_HOST -u DB_USER -p DB_PASSWORD \ --default-character-set=utf8 DB_NAME < DB_NAME-dump.sql
这是我的双重编码的UTF-8的100%修复。
资料来源: http : //blog.hno3.org/2010/04/22/fixing-double-encoded-utf-8-data-in-mysql/
如果你的utf8_encode()
已经是UTF-8的string了,那么当它被多次编码时,它看起来会出现乱码。
我做了一个函数toUTF8()
,将string转换为UTF-8。
你不需要指定你的string的编码是什么。 它可以是Latin1(ISO 8859-1),Windows-1252或UTF8或这三者的组合。
我自己用同一个string中的混合编码的feed。
用法:
$utf8_string = Encoding::toUTF8($mixed_string); $latin1_string = Encoding::toLatin1($mixed_string);
我的另一个函数fixUTF8()
修复了UTF8string多次被乱码的乱码。
用法:
$utf8_string = Encoding::fixUTF8($garbled_utf8_string);
例子:
echo Encoding::fixUTF8("Fédération Camerounaise de Football"); echo Encoding::fixUTF8("Fédération Camerounaise de Football"); echo Encoding::fixUTF8("FÃÂédÃÂération Camerounaise de Football"); echo Encoding::fixUTF8("Fédération Camerounaise de Football");
会输出:
Fédération Camerounaise de Football Fédération Camerounaise de Football Fédération Camerounaise de Football Fédération Camerounaise de Football
下载:
正如丹指出:你需要将它们转换为二进制,然后转换/更正编码。
例如,对于以latin1存储的utf8,以下SQL将修复它:
UPDATE table SET field = CONVERT( CAST(field AS BINARY) USING utf8) WHERE $broken_field_condition
我有一个xml文件的编码有问题,它说这是utf-8,但是它的字符不是utf-8。
经过几次与mb_convert_encoding()
试验和错误,我设法解决它
mb_convert_encoding($text, 'Windows-1252', 'UTF-8')
我知道这不是很优雅,但提到string可能是双重编码后,我做了这个function:
function fix_double encoding($string) { $utf8_chars = explode(' ', 'À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï Ð Ñ Ò Ó Ô Õ Ö × Ø Ù Ú Û Ü Ý Þ ß à á â ã ä å æ ç è é ê ë ì í î ï ð ñ ò ó ô õ ö'); $utf8_double_encoded = array(); foreach($utf8_chars as $utf8_char) { $utf8_double_encoded[] = utf8_encode(utf8_encode($utf8_char)); } $string = str_replace($utf8_double_encoded, $utf8_chars, $string); return $string; }
这似乎是完美的工作,以消除我遇到的双重编码。 我可能会错过一些可能成为别人问题的人物。 但是,为了我的需要,它是完美的工作。
方法是转换为二进制,然后正确的编码
另一件要检查的事情,就是我的解决scheme(在这里find),是从你的服务器返回数据。 在我的应用程序中,我使用PDO从PHP连接到MySQL。 我需要给连接添加一个标志,以UTF-8格式返回数据
答案是
$dbHandle = new PDO("mysql:host=$dbHost;dbname=$dbName;charset=utf8", $dbUser, $dbPass, array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8'"));
看起来你的utf-8在某些时候被解释为iso8859-1或者Win-1250。
当你说“在我的数据库中,我有一些不好的编码的例子” – 你是怎么检查的? 通过你的应用程序,phpmyadmin或命令行客户端? 所有的 utf-8编码都是这样显示还是只显示一些? 是不是有可能你的编码是错误的呢?当它已经是utf-8的时候,它被错误地从iso8859-1转换为utf-8了?
我很久以前也有同样的问题,并且使用了它
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-15">
我经过几天的searchfind了一个解决scheme。 我的评论将被埋葬,但无论如何…
-
我得到了与PHP的损坏的数据。
-
我不使用集合名称UTF8
-
我在我的数据上使用utf8_decode()
-
我用我的新的解码数据更新我的数据库,仍然不使用设置名称UTF8
和瞧:)
这个脚本有一个很好的方法。 把它转换成你select的语言不应该太难:
http://plasmasturm.org/log/416/
#!/usr/bin/perl use strict; use warnings; use Encode qw( decode FB_QUIET ); binmode STDIN, ':bytes'; binmode STDOUT, ':encoding(UTF-8)'; my $out; while ( <> ) { $out = ''; while ( length ) { # consume input string up to the first UTF-8 decode error $out .= decode( "utf-8", $_, FB_QUIET ); # consume one character; all octets are valid Latin-1 $out .= decode( "iso-8859-1", substr( $_, 0, 1 ), FB_QUIET ) if length; } print $out; }