web-dev-qa-db-ja.com

UTF-8文字に関する問題。私が見るものは私が保存したものではありません

UTF-8を使用しようとしましたが、問題が発生しました。

私は非常に多くのことを試しました。ここに私が得た結果があります:

  • アジア文字の代わりに????。ヨーロッパのテキストでも、Se?orSeñorを取得しました。
  • Señor新浪新闻の場合は新浪新闻などの奇妙な意味不明な(もじばけ?).
  • Seまたはなどのブラックダイヤモンド。
  • 最後に、データが失われるか、少なくとも切り捨てられる状況になりました:Se for Señor
  • look rightにテキストを受け取っても、sortが正しくありませんでした。

私は何を間違えていますか? codeを修正するにはどうすればよいですか? dataを回復できますか?

59
Rick James

この問題は、このサイトの参加者や他の多くの人々を悩ませています。

CHARACTER SETトラブルの5つの主なケースをリストしました。

ベストプラクティス

今後は、CHARACTER SET utf8mb4COLLATION utf8mb4_unicode_520_ciを使用するのが最適です。 (パイプラインにはUnicode照合の新しいバージョンがあります。)

utf8mb4は、utf8のスーパーセットであり、絵文字や一部の中国語で必要な4バイトのutf8コードを処理します。

MySQLの外部では、「UTF-8」はすべてのサイズのエンコーディングを指します。したがって、MySQLのutf8mb4ではなくutf8と事実上同じです。

以下では、これらのスペルと大文字を使用して、MySQLの内部と外部を区別しようとします。

あなたがすべきことの概要すべきことやる

  • エディターなどをUTF-8に設定してください。
  • HTMLフォームは<form accept-charset="UTF-8">のように開始する必要があります。
  • バイトをUTF-8としてエンコードします。
  • クライアントで使用されているエンコーディングとしてUTF-8を確立します。
  • 列/テーブルをCHARACTER SET utf8mb4と宣言します(SHOW CREATE TABLEで確認します。)
  • <meta charset=UTF-8> HTMLの先頭

TF-8全体

コンピューター言語の詳細 (および以下のセクション)

データをテストする

ツールまたはSELECTを使用してデータを表示することは信頼できません。そのようなクライアント、特にブラウザが多すぎると、誤ったエンコーディングを補正し、データベースが破損していても正しいテキストを表示しようとします。そのため、英語以外のテキストを含む表と列を選択して、

SELECT col, HEX(col) FROM tbl WHERE ...

正しく保存されたUTF-8のHEXは

  • 空白の場合(任意の言語):20
  • 英語の場合:4x5x6x、または7x
  • ほとんどの西ヨーロッパでは、アクセント記号付きの文字はCxyyでなければなりません
  • キリル文字、ヘブライ語、ペルシア語/アラビア語:Dxyy
  • アジアのほとんど:Exyyzz
  • 絵文字と中国語の一部:F0yyzzww
  • 詳細

見られた問題の特定の原因と修正

切り捨てられたテキスト(SeñorSe):

  • 格納されるバイトは、utf8mb4としてエンコードされません。これを修正してください。
  • また、読み取り中の接続がUTF-8であることを確認してください。

ブラックダイヤモンドと疑問符(Se�or for Señor);次のいずれかの場合があります。

ケース1(元のバイトはnotUTF-8):

  • 格納されるバイトはutf8としてエンコードされません。これを修正してください。
  • INSERTおよびSELECTの接続(またはSET NAMES)はutf8/utf8mb4ではありませんでした。これを修正してください。
  • また、データベースの列がCHARACTER SET utf8(またはutf8mb4)であることを確認します。

ケース2(元のバイトUTF-8):

  • SELECTの接続(またはSET NAMES)はutf8/utf8mb4ではありませんでした。これを修正してください。
  • また、データベースの列がCHARACTER SET utf8(またはutf8mb4)であることを確認します。

黒いひし形は、ブラウザが<meta charset=UTF-8>に設定されている場合にのみ発生します。

疑問符(黒い菱形ではなく通常のもの)(Se?or for Señor):

  • 格納されるバイトは、utf8/utf8mb4としてエンコードされません。これを修正してください。
  • データベースの列はCHARACTER SET utf8(またはutf8mb4)ではありません。これを修正してください。 (SHOW CREATE TABLEを使用します。)
  • また、読み取り中の接続がUTF-8であることを確認してください。

MojibakeSeñor for Señor):(この説明はDouble Encodingにも適用されます、必ずしも表示されるわけではありません。)

  • 格納するバイトはUTF-8エンコードする必要があります。これを修正してください。
  • INSERTingおよびSELECTingテキストがutf8またはutf8mb4を指定する必要がある場合の接続。これを修正してください。
  • 列はCHARACTER SET utf8(またはutf8mb4)として宣言する必要があります。これを修正してください。
  • HTMLは<meta charset=UTF-8>で始まる必要があります。

データは正しいように見えても正しくソートされない場合は、間違った照合を選択したか、ニーズに合った照合がないか、Double Encoding

ダブルエンコーディングは、上記のSELECT .. HEX ..を実行することで確認できます。

é should come back C3A9, but instead shows C383C2A9
The Emoji ???? should come back F09F91BD, but comes back C3B0C5B8E28098C2BD

つまり、ヘックスの長さは約2倍になります。これは、latin1(または何でも)からutf8に変換し、それらのバイトをlatin1であるかのように扱い、変換を繰り返すことにより発生します。たとえば、文字列がSeñorであるかのようにソートするため、ソート(および比較)は正しく機能しません。

データの修正、可能な場合

TruncationおよびQuestion Marksの場合、データは失われます。

Mojibake/Double Encoding、...

Black Diamonds、...

(別の質問/回答でこれを続けなければなりません。)

97
Rick James

サーバーの移行後、2つのプロジェクトで同様の問題が発生しました。多くのソリューションを検索して試した後、私はこれに出会いました:

mysqli_set_charset($con,"utf8");

この行を設定ファイルに追加すると、すべて正常に動作します!

Mysqliのこのソリューションを見つけました https://www.w3schools.com/PHP/func_mysqli_set_charset.asp HTMLクエリから挿入を解決しようとしていたとき

幸運を!

4
castro_pereira

面白い質問にあなた自身の質問に答える方法:)

  1. コードIDE言語をUTF8に設定します

  2. データフォームを収集するWebページヘッダーに追加します。

  3. MySQLテーブル定義が次のようになっていることを確認します。

    CREATE TABLE your_table (
      ...
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8
    
  4. PDOを使用している場合は、確認してください

    $options = array(PDO::MYSQL_ATTR_INIT_COMMAND=>'SET NAMES utf8'); 
    $dbL = new PDO($pdo, $user, $pass, $options);
    

上記の問題のある大規模なデータベースを既に取得している場合は、SIDUを試して正しい文字セットでエクスポートし、UTF8でインポートして戻すことができます。幸運を

2
SIDU