中国語文字化けの原因:デコード方法とエンコード方法が一致していません。 UTF-8 でエンコードされた中国語の文字は 3 バイトに変換され、gbk でエンコードされた場合は 2 バイトに変換され、UTF-8 でエンコードされた英語の文字は gbk でエンコードされた場合は 1 バイトに変換されます。 1バイトに変換されます。
このチュートリアルの動作環境: Windows 7 システム、Dell G3 コンピューター。
これを考えたことがある人はいるかわかりませんが、文字列には文字だけでなく、そのエンコード情報も含まれています。たとえば、Java では String str = "Hello" となります。前にも思いましたが、文字列 str はそのエンコード方式である Unicode エンコードや gbk、iso-8859-1 などを隠します。この理解は間違っています。文字は、他の情報を持たない文字です。人がファイル内で見る文字列は、システムが読み取ったメモリ内のデジタル情報であると理解するのが正しいでしょう。そして、それをいくつかの文字にデコードし、最終的に表示します。つまり、ダブルクリックしてテキスト ファイルを開くと、システムはメモリ内のデジタル情報を読み取って表示し、テキスト ファイルを保存すると、設定したエンコード方式でファイルをエンコードします。記憶に。 つまり、文字化けも一部の文字であり、単なる奇妙な文字であり、「コード」はありません。
コード化けの原因について話しましょうそこで聞きたいのは、なぜデコード方式とエンコード方式が異なると文字化けが発生するのかということです。
ここでは例として、utf-8、gbk、iso-8859-1 の 3 つのエンコード方式を示します。
@Test public void testEncode() throws Exception { String str = "你好",en = "h?h"; System.out.println("========中文字符utf-8======="); byte[] utf8 = str.getBytes(); // 以utf-8方式编码 ,default:utf-8 for (byte b : utf8) { System.out.print(b + "\t"); } System.out.println("\n"+"========英文字符utf-8======="); byte[] utf8_en = en.getBytes(); // 以utf-8方式编码 ,default:utf-8 for (byte b : utf8_en) { System.out.print(b + "\t"); } System.out.println("\n"+"========中文字符gbk========="); byte[] gbk = str.getBytes("gbk"); for (byte b : gbk) { System.out.print(b + "\t"); } System.out.println("\n"+"========英文字符gbk========="); byte[] gbk_en = en.getBytes("gbk"); for (byte b : gbk_en) { System.out.print(b + "\t"); } String s = new String(utf8,"utf-8"); String s1 = new String(utf8,"gbk"); System.out.println("\n"+s + "====gbk:" + s1); }
上記のメソッドをテストすると、出力される結果は次のようになります:
========中文字符utf-8======= -28 -67 -96 -27 -91 -67 ========英文字符utf-8======= 104 63 104 ========中文字符gbk========= -60 -29 -70 -61 ========英文字符gbk========= 104 63 104 你好====gbk:浣犲ソ ------------------------------------------------------------------------------------
次のように結論付けることができます:
中国語の文字が含まれていますutf-8 エンコードは 3 バイトに変換されます。gbk でエンコードされた場合は 2 バイトに変換されます。
utf- でエンコードされた英語文字8は1バイトに変換され、gbkでエンコードされた場合は1バイトに変換されます。
印刷の最後の行とコードの 29 ~ 31 行を組み合わせると、バイト配列 utf8 が utf-8 モードでデコードされると、文字化けがなければ元の「Hello」のままで、gbk モードでデコードすると文字化けが 3 つ表示されます。なぜ 2 ではなく 3 なのでしょうか? 6/2=3 です。
次に、iso-8859-1 について説明します。このエンコーディングは英語シリーズに適用されているため、中国語を表すことができません (これを使用したい場合は、互換性のある他のエンコーディングに依存する必要があります) ISO-8859-1 エンコード方式を使用します)。読めない文字は英語の疑問符 '?' として扱われます。ISO-8859-1 エンコードによる英語の疑問符の数は、63 (10 進数) です (実際、ほとんどすべてのエンコーディングでメソッドでは、Unicode エンコーディングを除き、すべての英語文字は 1 バイトコード表現で固定されます。
@Test public void testISO() throws Exception { String str = "你好"; byte[] bs = str.getBytes("iso-8859-1"); for (byte b : bs) { System.out.println(b); } System.out.println(new String(bs,"iso-8859-1")); System.out.println(new String(bs,"utf-8")); System.out.println(new String(bs,"gbk")); System.out.println(new String(bs,"unicode")); }
出力結果
63 63 ?? ?? ?? 㼿
説明 63 =》?、すべての中国語が考慮されます? したがって、このコードが実行されると、 byte[] bs = "Hello".getBytes ("iso-8859 -1");情報が失われました。
Execute String str = new String(bs, "any charset"); str は "Hello" ではなくなり、疑問符 2 つになります??。そのため、Tomcat では漢字が ???? という長い文字列に変化することがよくありますが、これが原因です。
iso-8859-1、utf-8、gbk では、1 バイトコードで英語の文字を表します
Unicode エンコードでは、1 バイトコードで文字を表すことはできず、規定されています文字を表すための 2 つのバイトコード (場合によっては 4)。
ここまで言うと、なぜこんなに多くのエンコード方式が使われているのかと疑問に思われるかもしれませんが、すべての文字を表現するにはutf-8に統一することはできないのでしょうか?
エンコーディングでは、文字を表現できるかどうかだけでなく、送信と保存も考慮されます。
1. UTF-8 は実際、ほぼすべての既知の文字を表すことができます。前述したように、UTF-8 エンコーディングでは漢字を表すのは 3 バイトのみであり、これは明らかにスペースを消費し、送信と保存には適していません (送信と保存は両方ともバイナリで実行されます)さまざまなエンコード方法のルールを理解する: https://jingyan.baidu.com/article/020278118741e91bcd9ce566.html2。 iso-8859-1 など、最もスペースを節約する方法では、1 バイトが 1 文字を表します。しかし、世界には英語だけではなく、さまざまな地域や国のキャラクターが存在します。したがって、文字数は 2 の 8 乗より大きくなければなりません。
したがって、上記の 2 つの点を組み合わせると、自然に多くのエンコード方法が現れます。
プログラミング関連の知識について詳しくは、プログラミング教育をご覧ください。 !
以上が中国語の文字化けの原因は何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。