修复破坏的UTF8编码

时间:2009-08-28 02:14:52

标签: php mysql unicode utf-8

我正在修复一些糟糕的UTF8编码。我目前正在使用PHP 5和MySQL

在我的数据库中,我有一些不良编码的实例,如:î

  • 数据库排序规则为utf8_general_ci
  • PHP正在使用正确的UTF8标头
  • Notepad ++设置为使用不带BOM的UTF8
  • 数据库管理在phpMyAdmin
  • 中处理
  • 并非所有重音字符都被破坏

我需要的是某种功能,它可以帮助我将î,ÃÂ,ü和其他类似的实例映射到正确的重音UTF8字符。

14 个答案:

答案 0 :(得分:92)

如果您有双重编码的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/

答案 1 :(得分:77)

如果你{1}}在一个已经是UTF-8的字符串上,那么当它被多次编码时它看起来很乱。

我创建了一个将字符串转换为UTF-8的函数utf8_encode()

您无需指定字符串的编码。它可以是Latin1(iso 8859-1),Windows-1252或UTF8,或者这三者的混合。

我自己在同一个字符串中使用混合编码的Feed中使用它。

用法:

toUTF8()

我的其他函数$utf8_string = Encoding::toUTF8($mixed_string); $latin1_string = Encoding::toLatin1($mixed_string); 修复了UTF8乱码,如果它们多次编码为UTF8。

用法:

fixUTF8()

示例:

$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");

下载:

https://github.com/neitanod/forceutf8

答案 2 :(得分:62)

过去我必须尝试'修复'一些UTF8破坏的情况,不幸的是,这绝不容易,而且往往是不可能的。

除非你能确切地确定它是如何被打破的,并且它总是以完全相同的方式被打破,否则很难“消除”这种伤害。

如果您想尝试撤消损坏,最好的办法是开始编写一些示例代码,您可以尝试对mb_convert_encoding()调用进行多种变化,看看是否可以找到'from'和''的组合''修复你的数据。最后,由于涉及到痛苦程度,通常最好不要担心修复旧数据,而是直接解决问题。

但是,在执行此操作之前,您需要确保首先解决导致此问题的所有问题。您已经提到您的数据库表格排序和编辑器设置正确。但是有更多地方需要检查以确保所有内容都是正确的UTF-8:

  • 确保您以UTF-8的形式提供HTML:
    • header(“Content-Type:text / html; charset = utf-8”);
  • 将PHP默认字符集更改为utf-8:
    • ini_set(“default_charset”,'utf-8');
  • 如果您的数据库始终没有在utf-8中通话,那么您可能需要在每个连接的基础上告诉它以确保它处于utf-8模式,在MySQL中您通过发出以下命令来实现:
    • charset utf8
  • 您可能需要告诉您的网络服务器始终尝试以UTF8进行通话,在Apache中,此命令是:
    • AddDefaultCharset UTF-8
  • 最后,您需要始终确保使用的是正确的UTF-8投诉的PHP函数。这意味着始终使用mb_*样式的“多字节识别”字符串函数。它还意味着在调用htmlspecialchars()等函数时,在末尾包含相应的'utf-8'charset参数,以确保它不会错误地对它们进行编码。

如果您错过了整个过程中的任何一步,编码可能会被破坏并出现问题。一旦你进入了做utf-8的'凹槽',这一切都成了第二天性。当然,PHP6应该是来自getgo的完全unicode投诉,这将使这很容易(希望如此)

答案 3 :(得分:11)

我的xml文件有一个打破了编码的问题,它说它是utf-8但它的字符不是utf-8。
经过多次试验和mb_convert_encoding()的错误后,我设法用

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

答案 4 :(得分:10)

正如Dan指出:你需要将它们转换为二进制,然后转换/更正编码。

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

UPDATE table
   SET field = CONVERT( CAST(field AS BINARY) USING utf8)
 WHERE $broken_field_condition

答案 5 :(得分:2)

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

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

这似乎可以完美地删除我遇到的双重编码。我可能错过了一些可能成为他人问题的角色。但是,根据我的需要,它工作得很好。

答案 6 :(得分:2)

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

答案 7 :(得分:1)

要检查的另一件事,恰好是我的解决方案(找到here),就是如何从服务器返回数据。在我的应用程序中,我使用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'"));

答案 8 :(得分:1)

就我而言,我使用“ mb_convert_encoding”发现以前的编码是iso-8859-1 (这是latin1),然后我通过使用sql查询解决了我的问题:

UPDATE myDB.myTable SET myColumn = CAST(CAST(CONVERT(myColumn USING latin1) AS binary) AS CHAR)

但是,在mysql文档中指出conversion may be lossy if the column contains characters that are not in both character sets.

答案 9 :(得分:0)

看起来你的utf-8在某些时候被解释为iso8859-1或Win-1250。

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

答案 10 :(得分:0)

很久以前我遇到了同样的问题,并使用

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

答案 11 :(得分:0)

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

  1. 我用php获取了损坏的数据。

  2. 我不使用集合名称UTF8

  3. 我在数据上使用utf8_decode()

  4. 我使用新的解码数据更新数据库,仍然没有使用集合名称UTF8

  5. 和voilà:)

答案 12 :(得分:0)

这个脚本有一个很好的方法。将其转换为您选择的语言应该不会太困难:

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

答案 13 :(得分:0)

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

实现这个表http://www.i18nqa.com/debug/utf8-debug.html