6

フランス語の人の名前とデータでいっぱいのこのデータベースを受け取りました。つまり、é、è、ö、ûなどの文字を使用しています。約3000エントリ。

どうやら、内部のデータはutf8_encode()を使用してエンコードされている場合と、そうでない場合があります。これにより、出力が混乱します。一部の場所では文字が正常に表示され、他の場所では表示されません。

最初は、これらの問題が発生するUIのすべての場所を追跡し、必要に応じてutf8_decode()を使用しようとしましたが、実際には実用的な解決策ではありません。

私はいくつかのテストを行いましたが、そもそもutf8_encodeを使用する理由はないので、すべてを削除して、ブラウザー、ミドルウェア、データベースの各レベルでUTF8で作業したいと思います。したがって、データベースをクリーンアップして、誤ってエンコードされたすべてのデータをクリーンアップされたバージョンで変換する必要があります。

質問:utf8文字列が正しくエンコードされているか(utf8_encodeなし)、正しくエンコードされていないか(utf8_encodeあり)をチェックする関数をphpで作成し、エンコードされている場合は元の状態に戻すことはできますか?

言い換えると、utf8_encode()されていないutf8コンテンツからutf8_encode()されていないutf8コンテンツを検出する方法を知りたいです。

**更新:例**

これが良い例です:あなたは特別な文字でいっぱいの文字列を取り、その文字列のコピーを取り、それをutf8_encode()します。私が夢見ている関数は両方の文字列を受け取り、最初の文字列はそのままにして、2番目の文字列は文字列1と同じになります。

私はこれを試しました:

$loc_fr = setlocale(LC_ALL, 'fr_BE.UTF8','fr_BE@euro', 'fr_BE', 'fr', 'fra', 'fr_FR');
$str1= "éèöûêïà ";
$str2 = utf8_encode($str1);

function convert_charset($str) {
    $charset=  mb_detect_encoding($str);
    if( $charset=="UTF-8" ) {
        return utf8_decode($str);
    }
    else {
        return $str;
    }
}
function correctString($str) {
    echo "\nbefore: $str";
    $str= convert_charset($str);
    echo "\nafter: $str"; 
}

correctString($str1);
echo('<hr/>'."\n");
correctString($str2);

そしてそれは私に与えます:

before: éèöûêïà after: ������� 
before: éèöûêïà  after: éèöûêïà 

ありがとう、

アレックス

4

5 に答える 5

6

現在どの文字エンコード レンズを使用しているか (これは、テキスト エディター、ブラウザー ヘッダー、データベース構成などの既定値によって異なります)、およびデータがどのような文字エンコード変換を行ったかは、質問から完全には明らかではありません。たとえば、データベース構成を微調整することですべてが修正される可能性があります。これは、データに断片的な変更を加えるよりもはるかに優れています。

utf8 の二重エンコードの問題である可能性があり、その場合、元のデータと破損したデータの両方が utf8 になるため、エンコードの検出では必要な情報が得られません。その場合のアプローチでは、データにどの文字が合理的に現れるかについて仮定を立てる必要があります。PHP と Mysql に関する限り、「é」は完全に合法的な utf8 です。データとその作成者は、データが破損している必要があります。あなたが単なる技術者である場合、これらは危険な仮定です。幸いなことに、データがフランス語であり、レコードが 3000 しかないことがわかっている場合は、おそらくそのような仮定を立てても問題ありません。

以下は、最初にデータをチェックし、次に修正し、最後に再度チェックするように適応できるスクリプトです。文字列を utf8 として処理し、文字に分割し、その文字を予想されるフランス語文字のホワイトリストと比較するだけです。文字列が utf8 ではないか、フランス語では通常予期されない文字が含まれている場合、問題を示します。次に例を示します。

PROBABLY OK     Côte d'Azur
HAS NON-WHITELISTED CHAR        Côte d'Azur    195,180 ô
NON-UTF8        C�e d'Azur

スクリプトは次のとおりです。依存する Unicode 関数をhttp://hsivonen.iki.fi/php-utf8/からダウンロードする必要があります。

<?php

// Download from http://hsivonen.iki.fi/php-utf8/
require "php-utf8/utf8.inc";

$my_french_whitelist = array_merge(
  range(0,127), // throw in all the lower ASCII chars
  array(
    0xE8, // small e-grave
    0xE9, // small e-acute
    0xF4, // small o-circumflex
    //... Will need to add other accented chars,
    // Euro sign, and whatever other chars
    // are normally expected in the data.
  )
);

// NB, whether this string literal is in utf8
// depends on the encoding of the text editor
// used to write the code
$str1 = "Côte d'Azur";
$test_data = array(
  $str1,
  utf8_encode($str1),
  utf8_decode($str1),
);

foreach($test_data as $str){
  $questionable_chars = non_whitelisted(
    $my_french_whitelist,
    $str
  );
  if($questionable_chars===true){
    p("NON-UTF8", $str);
  }else if ($questionable_chars){
    p(
      "HAS NON-WHITELISTED CHAR",
      $str,
      implode(",", $questionable_chars),
      unicodeToUtf8($questionable_chars)
    );
  }else{
    p("PROBABLY OK", $str);
  }
}

function non_whitelisted($whitelist, $utf8_str){
  $codepoints = utf8ToUnicode($utf8_str);
  if($codepoints===false){ // has non-utf8 char
    return true;
  }
  return array_diff(
    array_unique($codepoints),
    $whitelist
  );
}


function p(){
  $args = func_get_args();
  echo implode("\t", $args), "\n";
}
于 2009-10-02T00:02:30.173 に答える
2

もっとコンパイルのアプローチを取っているのではないかと思います。数週間前に、DB で動的にエンコードされたブルガリアのデータベースを受け取りましたが、それを別のデータベースに移動すると、ファンキーな???

私がそれを解決した方法は、データベースをダンプし、データベースをutf8照合に設定してから、データをバイナリとしてインポートすることでした。これにより、すべてがutf8に自動変換され、もう提供されませんでした???.

これはMySQLにありました

于 2009-10-02T15:42:00.537 に答える
2

データベースに接続するときは、常に mysql_set_charset('utf8', $db_connection); を使用することを忘れないでください。

それはすべてを修正し、すべての問題を解決しました。

これを参照してください: http://phpanswer.com/store-french-characters-into-mysql-db-and-display/

于 2010-08-15T02:11:05.720 に答える
0

私の問題は、どういうわけか、プレーン形式または utf8 でエンコードされたこれらの à、é、ê のようなデータベースの文字を取得したことです。調査の結果、送信フォームの処理に意図的に追加された utf8 エンコーディングがなかったため、一部のブラウザー (IE や FF などはわかりません) が送信された入力データをエンコードしているという結論に達しました。したがって、utf8_encode でデータを読み取る場合は、他のプレーン char を変更し、その逆も同様です。

上記のソリューションを検討した後の私のソリューション: 1. charset utf8 を使用して新しいデータベースを作成しました。3.元のデータベースからデータをインポートします(ここまでは、既存のデータベースとテーブルの文字セットを変更するだけで十分であり、元のデータベースがutf8でない場合のみ)4.utf8でエンコードされた文字を次のようなプレーンフォーマットがあります

UPDATE `clients` SET `name` = REPLACE(`name`,"é",'é' )  WHERE `name` LIKE CONVERT( _latin1 '%é%' USING utf8 ); 
  1. UTF8通信であることを確認するために、この行を(phpコード用に)dbクラスに入れました

    $this->query('SET CHARSET UTF8');

それで、更新しますか?(ステップ 4) エンコードされる可能性のある文字を含む配列を作成しました

$special_chars = array(
  'ù','û','ü',
  'ÿ',
  'à','â','ä','å','æ',
  'ç',
  'é','è','ê','ë',
  'ï','î',
  'ô','','ö','ó','ø',
  'ü');

更新する必要があるテーブル、フィールドのペアを含む配列を作成しました

$where_to_look = array(
    array("table_name" , "field_name"),
        ..... );

よりも、

    foreach($special_chars as $char)
    {
      foreach($where_to_look as $pair)
      {
        //$table = $pair[0]; $field = $pair[1]
        $sql = "SELECT id , `" . $pair[1] . "` FROM " .$pair[0] . " WHERE `" . $pair[1] . "` LIKE CONVERT( _latin1 '%" . $char . "%' USING utf8 );";

    if($db->num_rows() > 0){
         $sql1 = "UPDATE " . $pair[0] . " SET `" . $pair[1] . "` = REPLACE(`" . $pair[1] . "`,CONVERT( _latin1 '" . $char . "' USING utf8 ),'" . $char . "' )  WHERE `" . $pair[1] . "` LIKE CONVERT( _latin1 '%" . $char . "%' USING utf8 )";
         $db1->query($sql1);
        }
    }
 }

基本的な考え方は、mysql のエンコーディング機能を使用して、mysql、apache、ブラウザ、およびその逆の間で行われるエンコーディングを回避することです。注: mb_ のような利用可能な php 関数がありませんでした....

一番

于 2009-10-23T11:00:10.447 に答える
0

データは を使用して変換されることがあるとおっしゃっていたように、データはutf8_encodeUTF-8 または ISO 8859-1 のいずれかでエンコードされます ( utf8_encodeISO 8859-1 から UTF-8 に変換されるため)。UTF-8 は 128 から 255 までの文字を 1100001x で始まる 2 バイトでエンコードするため、データが有効な UTF-8 であるかどうかをテストし、有効でない場合は変換するだけです。

そのため、すでに UTF-8 である場合はすべてのデータをスキャンし (いくつかのis_utf8関数を参照)、utf8_encodeUTF-8 でない場合は使用します。

于 2009-10-01T12:06:21.530 に答える