ホームページ >よくある問題 >中国語の文字化けの原因は何ですか?

中国語の文字化けの原因は何ですか?

青灯夜游
青灯夜游オリジナル
2022-11-09 11:14:0438157ブラウズ

中国語文字化けの原因:デコード方法とエンコード方法が一致していません。 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 バイトのみであり、これは明らかにスペースを消費し、送信と保存には適していません (送信と保存は両方ともバイナリで実行されます)

2。 iso-8859-1 など、最もスペースを節約する方法では、1 バイトが 1 文字を表します。しかし、世界には英語だけではなく、さまざまな地域や国のキャラクターが存在します。したがって、文字数は 2 の 8 乗より大きくなければなりません。

したがって、上記の 2 つの点を組み合わせると、自然に多くのエンコード方法が現れます。

さまざまなエンコード方法のルールを理解する: https://jingyan.baidu.com/article/020278118741e91bcd9ce566.html

プログラミング関連の知識について詳しくは、プログラミング教育をご覧ください。 !

以上が中国語の文字化けの原因は何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。