私はいくつかの悪いUTF-8エンコーディングを修正する過程にあります。現在、PHP 5とMySQLを使用しています。
私のデータベースには、次のように表示されるエンコードが正しくないインスタンスがいくつかあります。
î、ÃÂ、üなどのインスタンスを適切なアクセント付きUTF-8文字にマッピングするのに役立つ何らかの機能が必要です。
私は過去に多くのUTF8の壊れた状況を「修正」しなければなりませんでしたが、残念ながらそれは決して簡単ではなく、しばしば不可能です。
どのように破損したかを正確に判断できず、常にまったく同じ方法で破損した場合を除き、損傷を「元に戻す」ことは困難になります。
損傷を取り消そうとする場合、最善の方法は、いくつかのサンプルコードの記述を開始することです。ここでは、mb_convert_encoding()の呼び出しで多数のバリエーションを試し、「from」と「to」の組み合わせを見つけることができるかどうかを確認しますデータを修正します。結局、苦痛のレベルが関係しているために古いデータの修正を気にすることさえせずに、代わりに物事を修正することが最善です。
ただし、これを行う前に、この問題の原因となっているすべてのものを最初に修正する必要があります。 DBテーブルの照合とエディターが適切に設定されていることは既に述べました。しかし、すべてが適切に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/
すでにUTF-8である文字列に対してutf8_encode()
を使用すると、複数回エンコードされたときに文字化けします。
文字列をUTF-8に変換する関数toUTF8()
を作成しました。
文字列のエンコーディングを指定する必要はありません。 Latin1(iso 8859-1)、Windows-1252、UTF8、またはこれら3つの組み合わせを使用できます。
同じ文字列にエンコードが混在するフィードでこれを自分で使用しました。
使用法:
_$utf8_string = Encoding::toUTF8($mixed_string);
$latin1_string = Encoding::toLatin1($mixed_string);
_
私の他の関数fixUTF8()
は、UTF8に複数回エンコードされた場合、文字化けしたUTF8文字列を修正します。
使用法:
_$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
_
ダウンロード:
エンコードが壊れているxmlファイルに問題があり、utf-8であると言っていましたが、utf-8ではない文字がありました。mb_convert_encoding()
で何度か試行錯誤を繰り返した後、
mb_convert_encoding($text, 'Windows-1252', 'UTF-8')
Danが指摘したように、それらをバイナリに変換してから、エンコードを変換/修正する必要があります。
たとえば、latin1として保存されたutf8の場合、次のSQLで修正されます。
UPDATE table
SET field = CONVERT( CAST(field AS BINARY) USING utf8)
WHERE $broken_field_condition
これはあまりエレガントではないことは知っていますが、文字列が二重にエンコードされている可能性があると述べた後、この関数を作成しました:
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;
}
これは、私が経験している二重エンコードを削除するのに完全に機能するようです。他の人にとっては問題になる可能性のあるキャラクターのいくつかが欠けているのでしょう。しかし、私のニーズには完全に機能しています。
方法は、バイナリに変換してからエンコードを修正することです
確認すべきもう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'"));
私はずっと前に同じ問題を抱えていましたが、それを使用して修正しました
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-15">
Utf-8は、ある時点でiso8859-1またはWin-1250として解釈されているようです。
「私のデータベースでは、いくつかの不適切なエンコーディングのインスタンスがあります」と言うとき、これをどのように確認しましたか?アプリ、phpmyadmin、またはコマンドラインクライアントから? all utf-8エンコーディングはこのように表示されますか、それとも一部のみ表示されますか?エンコードが間違っていて、すでにutf-8であったときにiso8859-1からutf-8に誤って変換された可能性はありますか?
数日間の検索で解決策を見つけました。私のコメントは埋葬されますが、とにかく...
破損したデータをphpで取得します。
セット名UTF8を使用しません
データでutf8_decode()を使用します
UTF8のセット名を使用せずに、新しいデコードされたデータでデータベースを更新します
そしてボイラ:)
このスクリプトにはすてきなアプローチがありました。選択した言語に変換するのはそれほど難しくないはずです。
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;
}