Php 修复损坏的UTF-8编码

Php 修复损坏的UTF-8编码,php,mysql,unicode,utf-8,Php,Mysql,Unicode,Utf 8,我正在修复一些糟糕的UTF-8编码。我目前正在使用PHP5和MySQL 在我的数据库中,我有一些错误编码的实例,它们的打印格式如下:î 数据库排序规则为utf8\u general\u ci PHP使用的是正确的UTF-8头 Notepad++设置为使用不带BOM的UTF-8 数据库管理在中处理 并不是所有重音字符的大小写都是断开的 我需要某种函数来帮助我将î、ޠƒ、ޠƒ¼和其他类似的实例映射到它们正确的重音UTF-8字符。看起来您的UTF-8在某个时候被解释为iso8859-1或W

我正在修复一些糟糕的UTF-8编码。我目前正在使用PHP5和MySQL

在我的数据库中,我有一些错误编码的实例,它们的打印格式如下:î

  • 数据库排序规则为utf8\u general\u ci
  • PHP使用的是正确的UTF-8头
  • Notepad++设置为使用不带BOM的UTF-8
  • 数据库管理在中处理
  • 并不是所有重音字符的大小写都是断开的

我需要某种函数来帮助我将î、ޠƒ、ޠƒ¼和其他类似的实例映射到它们正确的重音UTF-8字符。

看起来您的UTF-8在某个时候被解释为iso8859-1或Win-1250


当您说“在我的数据库中,我有一些错误编码的实例”时,您是如何检查的?通过你的应用,phpmyadmin还是命令行客户端?所有的utf-8编码都是这样显示的还是只有一部分?有没有可能您的编码错误,并且当它已经是utf-8时,它被错误地从iso8859-1转换为utf-8?

我曾经尝试过“修复”一些UTF8中断的情况,不幸的是,这从来都不容易,而且常常是不可能的

除非你能准确地确定它是如何被破坏的,而且它总是以完全相同的方式被破坏,否则很难“修复”损坏

如果您想尝试撤消损坏,最好的办法是开始编写一些示例代码,在调用
mb\u convert\u encoding()
时尝试多种变体,看看是否可以找到修复数据的“from”和“to”组合。最后,最好不要因为涉及的痛苦程度而担心修复旧数据,而是继续修复

但是,在执行此操作之前,您需要确保首先修复导致此问题的所有问题。您已经提到DB表排序规则和编辑器设置正确。但还有更多的地方需要检查,以确保所有内容都正确使用UTF-8:

  • 确保将HTML作为UTF-8提供:
    • 标题(“内容类型:text/html;字符集=utf-8”)
  • 将PHP默认字符集更改为utf-8:
    • ini\u集(“默认字符集”,“utf-8”)
  • 如果您的数据库不总是使用utf-8,那么您可能需要在每个连接的基础上告诉它,以确保它处于utf-8模式,在MySQL中,您可以通过发出:
    • 字符集utf8
  • 您可能需要告诉您的Web服务器始终尝试使用UTF8进行对话,在Apache中,此命令是:
    • AddDefaultCharset UTF-8
  • 最后,您需要始终确保您使用的PHP函数是正确的UTF-8。这意味着始终使用样式化的“多字节感知”字符串函数。这还意味着在调用函数(如
    htmlspecialchars()
    )时,在末尾包含适当的“utf-8”字符集参数,以确保不会对其进行错误编码

如果您错过了整个过程中的任何一个步骤,编码可能会被破坏,并出现问题。一旦你进入了utf-8的“最佳状态”,这一切就变成了你的第二天性。当然,PHP6应该是完全由getgo提供的unicode编码,这将使很多事情变得更容易(希望)

我知道这不是很优雅,但在提到字符串可能是双重编码后,我做了这个函数:

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;
}

这似乎完美地消除了我所经历的双重编码。我可能错过了一些对其他人来说可能是个问题的角色。但是,出于我的需要,它工作得很好。

方法是将其转换为二进制,然后进行正确的编码。

正如丹指出的那样:您需要将其转换为二进制,然后转换/纠正编码

例如,对于存储为latin1的utf8,以下SQL将修复它:

UPDATE table
   SET field = CONVERT( CAST(field AS BINARY) USING utf8)
 WHERE $broken_field_condition
如果对一个已经是UTF-8的字符串执行
utf8\u encode()
,那么当它被多次编码时,它看起来是乱码

我制作了一个函数
toUTF8()
,将字符串转换为UTF-8

您不需要指定字符串的编码是什么。它可以是拉丁文1(iso 8859-1)、Windows-1252或UTF8,也可以是这三种语言的混合

我自己在一个提要中使用了这个,在同一个字符串中使用了混合编码

用法:

$utf8_string = Encoding::toUTF8($mixed_string);

$latin1_string = Encoding::toLatin1($mixed_string);
$utf8_string = Encoding::fixUTF8($garbled_utf8_string);
我的另一个函数
fixUTF8()
修复了多次被编码到UTF8中的乱码UTF8字符串

用法:

$utf8_string = Encoding::toUTF8($mixed_string);

$latin1_string = Encoding::toLatin1($mixed_string);
$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
下载:


如果您有双编码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
mysqldump-h DB_HOST-u DB_USER-p DB_PASSWORD--opt--quote name\
--跳过集字符集--默认字符集=latin1 DB_NAME>DB_NAME-dump.sql
mysql-hdb_主机-udb_用户-pdb_密码\
--默认字符集=utf8 DB\u NAME
这是我的双编码UTF-8的100%修复

资料来源:

很久以前我也遇到过同样的问题,它使用

<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-15">

经过几天的搜索,我找到了一个解决方案。我的评论将被埋葬,但无论如何

  • 我用php获取损坏的数据

  • 我不使用集合名UTF8

  • 我对数据使用utf8_decode()

  • 我用新的解码数据更新数据库,但仍然不使用集合名UTF8


  • 瞧:)

    我对一个编码错误的xml文件有一个问题,它说是utf-8,但它的字符不是utf-8。
    在使用
    mb\u convert\u encoding()
    进行了多次尝试并出错之后,我设法用

    mb_convert_encoding($text, 'Windows-1252', 'UTF-8')
    

    还有一件事要检查,发生在t
    UPDATE myDB.myTable SET myColumn = CAST(CAST(CONVERT(myColumn USING latin1) AS binary) AS CHAR)
    
    $bad_string = "Luis Pérez Casas, del Collettivo di avvocati “José Alvear Restrepoâ€, Colombia, un’organizzazione soggetta a costanti minacce";
    
    $good_string = fix_broken_chars($bad_string);
    
    echo $good_string;
    
    function fix_broken_chars($garbled_utf8_string)
    {   
        $conv_table = unserialize('a:5:{i:0;a:3:{s:8:"’";s:3:"’";s:8:"–";s:3:"–";s:8:"—";s:3:"—";}i:1;a:12:{s:7:"€";s:3:"€";s:7:"‚";s:3:"‚";s:7:"„";s:3:"„";s:7:"…";s:3:"…";s:7:"‡";s:3:"‡";s:7:"‰";s:3:"‰";s:7:"‹";s:3:"‹";s:7:"‘";s:3:"‘";s:7:"“";s:3:"“";s:7:"•";s:3:"•";s:7:"â„¢";s:3:"™";s:7:"›";s:3:"›";}i:2;a:22:{s:5:"À";s:2:"À";s:5:"Â";s:2:"Â";s:5:"Æ’";s:2:"ƒ";s:5:"Ä";s:2:"Ä";s:5:"Ã…";s:2:"Å";s:5:"â€";s:3:"”";s:5:"Æ";s:2:"Æ";s:5:"Ç";s:2:"Ç";s:5:"ˆ";s:2:"ˆ";s:5:"É";s:2:"É";s:5:"Ë";s:2:"Ë";s:5:"Å’";s:2:"Œ";s:5:"Ñ";s:2:"Ñ";s:5:"Ã’";s:2:"Ò";s:5:"Ó";s:2:"Ó";s:5:"Ô";s:2:"Ô";s:5:"Õ";s:2:"Õ";s:5:"Ö";s:2:"Ö";s:5:"×";s:2:"×";s:5:"Ù";s:2:"Ù";s:5:"Û";s:2:"Û";s:5:"Å“";s:2:"œ";}i:3;a:77:{s:4:"Ã";s:2:"Ã";s:4:"È";s:2:"È";s:4:"Ê";s:2:"Ê";s:4:"ÃŒ";s:2:"Ì";s:4:"Ž";s:2:"Ž";s:4:"ÃŽ";s:2:"Î";s:4:"Ëœ";s:2:"˜";s:4:"Ø";s:2:"Ø";s:4:"Å¡";s:2:"š";s:4:"Ú";s:2:"Ú";s:4:"Ãœ";s:2:"Ü";s:4:"ž";s:2:"ž";s:4:"Þ";s:2:"Þ";s:4:"Ÿ";s:2:"Ÿ";s:4:"ß";s:2:"ß";s:4:"¡";s:2:"¡";s:4:"á";s:2:"á";s:4:"¢";s:2:"¢";s:4:"â";s:2:"â";s:4:"£";s:2:"£";s:4:"ã";s:2:"ã";s:4:"¤";s:2:"¤";s:4:"ä";s:2:"ä";s:4:"Â¥";s:2:"¥";s:4:"Ã¥";s:2:"å";s:4:"¦";s:2:"¦";s:4:"æ";s:2:"æ";s:4:"§";s:2:"§";s:4:"ç";s:2:"ç";s:4:"¨";s:2:"¨";s:4:"è";s:2:"è";s:4:"©";s:2:"©";s:4:"é";s:2:"é";s:4:"ª";s:2:"ª";s:4:"ê";s:2:"ê";s:4:"«";s:2:"«";s:4:"ë";s:2:"ë";s:4:"¬";s:2:"¬";s:4:"ì";s:2:"ì";s:4:"­";s:2:"­";s:4:"í";s:2:"í";s:4:"®";s:2:"®";s:4:"î";s:2:"î";s:4:"¯";s:2:"¯";s:4:"ï";s:2:"ï";s:4:"°";s:2:"°";s:4:"ð";s:2:"ð";s:4:"±";s:2:"±";s:4:"ñ";s:2:"ñ";s:4:"²";s:2:"²";s:4:"ò";s:2:"ò";s:4:"³";s:2:"³";s:4:"ó";s:2:"ó";s:4:"´";s:2:"´";s:4:"ô";s:2:"ô";s:4:"µ";s:2:"µ";s:4:"õ";s:2:"õ";s:4:"¶";s:2:"¶";s:4:"ö";s:2:"ö";s:4:"·";s:2:"·";s:4:"÷";s:2:"÷";s:4:"¸";s:2:"¸";s:4:"ø";s:2:"ø";s:4:"¹";s:2:"¹";s:4:"ù";s:2:"ù";s:4:"º";s:2:"º";s:4:"ú";s:2:"ú";s:4:"»";s:2:"»";s:4:"û";s:2:"û";s:4:"¼";s:2:"¼";s:4:"ü";s:2:"ü";s:4:"½";s:2:"½";s:4:"ý";s:2:"ý";s:4:"¾";s:2:"¾";s:4:"þ";s:2:"þ";s:4:"¿";s:2:"¿";s:4:"ÿ";s:2:"ÿ";}i:4;a:1:{s:2:"Ã";s:2:"à";}}');
    
        foreach ($conv_table as $convert) {
            $garbled_utf8_string = str_replace(array_keys($convert), $convert, $garbled_utf8_string);    
        }
    
        return $garbled_utf8_string;
    }