Qt漢字文字化けしの分析

9432 ワード

まず、QStringには中国語のサポートの問題は存在しません.多くの人が問題に直面しています.自分のQStringの問題ではなく、自分の希望する文字列をQStringに正しく与えていません.簡単な問題ですが、「私は中国語です」と書くときは、伝統的なcharタイプの狭い文字列で、QStringという4つの漢字に採用されているコードを何らかの方法で教えるだけです.問題は一般的に多くのユーザーが自分の現在の符号化にあまり概念を持っていないことである.

簡単なQtプログラム


 
次の小さなプログラムは、皆さんが親切に感じると思います.このようなコードを書くことを試みた中国語ユーザーはかなり多いようです.
#include <QtGui/QApplication>
#include <QtGui/QLabel>

int main(int argc, char **argv)
{
    QApplication app(argc, argv);
    QString a= " ";
    QLabel label(a);
    label.show();
    return app.exec();
}

コーディング、保存、コンパイル、実行、すべては順調でしたが、結果は:
多くのユーザーが
他のユーザーが表示
ÎÒÊǺº×Ö
æˆ‘æ˜¯æ±‰å —

意外なことに、インタフェースに中国語が表示されず、文字を知らない人が現れた.そこで検索エンジンで検索し始め、掲示板に投稿したり文句を言ったりします.
最後に、次の文の1つが問題を解決できることを示します.
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("GB2312"));
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));

2つの命令は1つずつ試して、確かに解決することができます(多くのユーザーは第1条で、他のユーザーは第2条です).では、なぜそうなるのでしょうか.

2つの文字化けしはいつ現れますか


この問題について、みんなが話しているかもしれないと思います.続行する前に、2つの文字化けしがそれぞれその場合に現れるのを見てみましょう.
最も一般的な3つのコンパイラ(マイクロソフトVSの中のcl,Mingwの中のg+,Linuxの下のg++)のみを列挙し,ソースコードはそれぞれGBKとBOMを持たないUTF-8,BOM付きUTF-8の3つのコードで保存した.
ソースコードのコーディング
コンパイラ
結果
 
GBK
cl
1
*
mingw-g++
1
*
g++
1
 
UTF-8(BOMなし)
cl
2
 
mingw-g++
2
 
g++
2
*
UTF-8(BOM付き)
cl
1
 
mingw-g++
2
 
g++
コンパイル失敗
 

3種類の異なる符号化で保存されたソースファイルを用いて,それぞれ3種類の異なるコンパイラでコンパイルし,9種類の組合せを形成し,1つの動作できない場合を除き,2つの乱符号が発生する場合はそれぞれ半分を占める.
文字化けしてオペレーティングシステムとは関係ないことも分かる.しかし、Windowsで一般的に使われているGBK、linuxではBOMを持たないUTF-8が一般的です.もし私たちが*付きの場合だけを考慮すれば、2つの文字化けはシステムと関係があると言ってもいい.

QStringはなぜ文字化けしたのか


本当にQString文字化けしたのかな?私たちが文句を言っている相手が間違っているのではないかと自分に聞いてみましょう.
続行する前に、いくつかの概念を明確にします.

明確な概念0:

  • 「私は漢字です」はC言語の文字列で、char型の狭い文字列です.上記の例は
  • と書くことができます.
    const char * str = " ";
    QString a= str;

    または
    char str[] = " ";
    QString a= str;

    など

    明確な概念1:

  • ソースファイルは符号化されているが、このような純粋なテキストファイルは、自分が採用する符号化
  • を記録しない.
    これは問題の根源で、前のソースコードをGBK符号化に保存して、16進法エディタで引用符の中にce d 2 ca c 7 ba ba d 7 d 6のような8バイトが見えるように実験してみてはいかがでしょうか.
    現在、このファイルを正体(繁体字)中国語のWindowsにコピーし、手帳で開くとどうなりますか?
    ...
        QString a= " ";
        QLabel label(a);
        label.show();
    ...

    では、欧米人のWindowsシステムに入れて、手帳で開くのでしょうか.
    ...
        QString a= "ÎÒÊǺº×Ö";
        QLabel label(a);
        label.show();
    ...

    同じ文書では、何の修正も行われていないが、そのうち8バイトのce d 2 ca c 7 ba ba d 7 d 6は、GBKを使った大陸人、BIG 5を使った香港・マカオ・台湾の同胞、Latin-1を使ったヨーロッパ人から見れば、全く異なる文字を見ている.

    明確な概念2:

  • は、私たちが知っている「A」が「x 41」と等価であるように.

  • GBK符号化下の
    const char * str = " "

    に等しい
    const char * str = "\xce\xd2\xca\xc7\xba\xba\xd7\xd6";

    UTF-8で符号化する場合、
    const char * str = "\xe6\x88\x91\xe6\x98\xaf\xe6\xb1\x89\xe5\xad\x97";

    注意:この言い方は完全に正しいわけではありません.例えば、BOM付きUTF-8として保存され、clコンパイラでは漢字自体がUTF-8符号化されていますが、プログラム内で保存されている場合は対応するGBK符号化です.

    明確な概念3:

  • QString内部にはUnicodeが採用されています.

  • QStringの内部にはUnicodeが採用されており、GBKの文字「私は漢字です」、BIG 5の文字「×Ö".
    1つの問題は、ソースコードの8バイト「xcexd 2xcaxc 7xbaxbaxd 7xd 6」をどのようにUnicodeに変換してQString内に併存するかということです.GBK、BIG 5、Latin-1か他の方法で...
    あなたが教えてくれない場合、デフォルトでLatin-1を選択し、8文字の「×中国共産党のunicodeコードはQStringに保存されています.最終的には、8つのLatin文字が4つの中国語文字を見たい場所に現れ、いわゆる文字化けしが現れました

    QString動作方式

    const char * str = " ";
    QString a= str;

    実は簡単な問題ですが、狭い文字列char*からUnicodeのQString文字列に変換する必要がある場合は、QStringのchar*の中で何の符号化があるのかを教えてあげる必要があります.GBK、BIG5、Latin-1
    理想的には、char*をQStringに渡すと同時に、QString自身のコードが何であるかを教えます.
    次の関数のように、QStringのメンバー関数は、C文字列をどのような符号化で処理するかを知っています.
    QString QString::fromAscii ( const char * str, int size = -1 )
    QString QString::fromLatin1 ( const char * str, int size = -1 ) 
    QString QString::fromLocal8Bit ( const char * str, int size = -1 )
    QString QString::fromUtf8 ( const char * str, int size = -1 )

    単QStringはこのいくつかのメンバー関数だけを提供して、みんなの需要をはるかに満たすことができません.例えば、簡体字中国語Windowsの下で、local 8 BitはGBKですが、char列がBIG 5かLatin-2ではどうしますか.
    では、強力なQTextCodecを動員しましょう.まず、QTextCodecは自分が担当しているコードを知っているに違いありません.それからchar列を送ります.それは正しくUnicodeに変えることができます.
    QString QTextCodec::toUnicode ( const char * chars ) const

    しかし、この呼び出しは面倒で、私は直接
    QString a= str;

    または
    QString a(str);

    このように使ったらどうしますか.
    これでは、QStringのstrがどのようにコードされているかを同時に教えることはできません.他の方法しかありません.これが冒頭の
    QTextCodec::setCodecForCStrings(QTextCodec::codecForName("GBK"));
    QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));

    QStringのデフォルトで使用するエンコーディングを設定します.どちらを採用するかというと、一般的にはソースコードがGBKであり、GBKであり、ソースコードがUTF-8であればUTF-8である.しかし、例外として、BOM付きUTF-8で使用されているマイクロソフトのclコンパイラに保存されている場合は、GBKです.
     
    まとめると、文字化けしの原因は主に以下の通りです.
    QStringの内部にはUnicodeが採用されており、GBKの文字「私は漢字です」、BIG 5の文字「×Ö".
    狭い文字列char*からUnicodeのQString文字列に変換する必要がある場合は、QStringにこのchar*の中で何の符号化があるのかを伝える必要があります.GBK、BIG5、Latin-1?
    あなたが教えてくれない場合、デフォルトでLatin-1を選択し、8文字の「×中国共産党のunicodeコードはQStringに保存されています.最終的には、8つのLatin文字が4つの中国語文字を見たい場所に現れます.
    いわゆる文字化けしが現れた.
    ネット上ではmainに直接紹介する方法がたくさんあります.cppで設定:
        QTextCodec *codec = QTextCodec::codecForName("UTF-8");
        QTextCodec::setCodecForTr(codec);
        QTextCodec::setCodecForLocale(codec);     QTextCodec::setCodecForCStrings(codec);
    実際には、プログラムがシステムの中国語パスを読み取るか、中国語パスの下の外部プログラムを呼び出す可能性があるため、システムがgb 2312であれば問題があります.
    中国語パスの符号化はutf-8を用いてQStringに格納されているため、システムが中国語パスを読んで復号する際に採用するのはシステムのgb 2312であるため、中国語パス付きの外部プログラムを呼び出すことができない.
    以上の問題は次の方法で解決できます.
        QTextCodec *codec = QTextCodec::codecForName("UTF-8");
        QTextCodec::setCodecForTr(codec);
        QTextCodec::setCodecForLocale(QTextCodec::codecForLocale());     QTextCodec::setCodecForCStrings(QTextCodec::codecForLocale());
    外部文字列符号化復号にはすべてローカル符号化が用いられる.