18

私は、「常に std::wstring を使用する」と言われている Windows 用の英語のみの C++ プログラムに取り組んでいますが、チームの誰もそれ以上のことを本当に理解していないようです。

「 std::wstring VS std::string 」というタイトルの質問をすでに読みました。非常に役に立ちましたが、そのすべての情報を問題に適用する方法がまだよくわかりません。

私が取り組んでいるプログラムは、Windows GUI にデータを表示します。そのデータは XML として永続化されます。レポーティングのために、XSLT を使用してその XML を HTML または XSL:FO に変換することがよくあります。

私が読んだ内容に基づく私の感覚は、HTML は UTF-8 としてエンコードする必要があるということです。私は GUI 開発についてほとんど知りませんが、少し読んだだけでは、GUI はすべて UTF-16 でエンコードされた文字列に基づいていることがわかります。

私はこれが私をどこに残すかを理解しようとしています。永続化されたデータはすべて UTF-8 でエンコードされた XML にする必要があると判断したとします。これは、永続化されたデータを UI コンポーネントに表示するには、何らかの明示的な UTF-8 から UTF-16 へのトランスコーディング プロセスを実際に実行する必要があるということですか?

私の説明は明確化を使用できると思われるので、質問があればそれを提供しようとします.

4

5 に答える 5

9

NT4 以降の Windows は、Unicode でエンコードされた文字列に基づいています。初期のバージョンは、UTF-16 の前身である UCS-2 に基づいていたため、UTF-16 がサポートするすべての文字をサポートしていません。それ以降のバージョンは UTF-16 に基づいています。ただし、すべての OS が UTF-16/UCS-2 に基づいているわけではありません。たとえば、*nix システムは代わりに UTF-8 に基づいています。

UTF-8 は、データを永続的に保存するための非常に優れた選択肢です。これは、すべての Unicode 環境で広くサポートされているエンコーディングであり、データ サイズと損失のないデータ互換性のバランスが取れています。

はい、XML を解析し、そこから必要な情報を抽出し、デコードして、UI が使用できるものに変換する必要があります。

于 2010-03-27T01:06:49.420 に答える
7

std::wstring は技術的には UCS-2 です。各文字に 2 バイトが使用され、コード テーブルはほとんどUnicode 形式にマップされます。UCS-2 は UTF-16 と同じではないことを理解することが重要です! UTF-16 では、2 バイトの範囲外の文字を表すために「サロゲート ペア」を使用できますが、UCS-2 では各文字、ピリオドに正確に 2 バイトを使用します。

状況に応じた最適なルールは、ディスクの読み取りおよび書き込み時にトランスコーディングを行うことです。メモリに保存したら、UCS-2 形式で保存します。Windows API はそれを UTF-16 であるかのように読み取ります (つまり、手動で作成した場合、std::wstring はサロゲート ペアの概念を理解していません (使用している唯一の言語が英語)、Windows が読み取ります)。

現代では、シリアライゼーション形式 (XML など) の内外でデータを読み取るときはいつでも、おそらくトランスコーディングを行う必要があります。これは不愉快で非常に不幸な現実ですが、Unicode は可変幅の文字エンコーディングであり、C++ でのほとんどの文字ベースの操作は配列として行われるため、一貫した間隔が必要になるため、避けられません。

.NET などの高レベルのフレームワークは、ほとんどの詳細を覆い隠していますが、舞台裏では、可変幅データを固定幅文字列に変更し、それらを操作してから変更するという同じ方法でトランスコーディングを処理しています。出力に必要な場合は、可変幅エンコーディングに戻します。

于 2010-03-27T01:12:58.827 に答える
6

私の知る限り、WindowsでC++でstd::wstringを使用し、UTF-8を使用してファイルに保存する場合(これは適切で合理的に聞こえます)、ファイルに書き込むときにデータをUTF-8に変換し、元に戻す必要がありますファイルから読み取る場合は UTF-16。このリンクをチェックしてください: Writing UTF-8 Files in C++

プロジェクトのVisual Studioのデフォルト->プロパティ->構成プロパティ->一般->文字セット-> Unicode文字セットを使用し、wchar_tタイプを使用し(つまり、std::wstringを使用) 、TCHARタイプを使用しません。(たとえば、_tcslen ではなく、strlen の wcslen バージョンを使用します。)

于 2010-03-27T02:49:34.497 に答える
3

Windows で GUI 関連の文字列に std::wstring を使用する利点の 1 つは、すべての Windows API 呼び出しが内部的に UTF-16 を使用して動作することです。文字列引数を取るすべての Win32 API 呼び出しには 2 つのバージョンがあることにお気づきでしょうか。たとえば、「MessageBoxA」と「MessageBoxW」です。両方の定義が に存在し、実際にはどちらでも呼び出すことができますが、 が Unicode サポートを有効にして含まれている場合は、次のようになります。

#define MessageBox MessageBoxW

次に、TCHAR やその他の Microsoft のトリックを使用して、ANSI と Unicode の両方のバージョンを持つ API を簡単に扱えるようにします。要するに、どちらでも呼び出すことができますが、内部では Windows カーネルが Unicode ベースであるため、ワイド char バージョンを使用しない場合、Win32 API 呼び出しを受け入れる文字列ごとに Unicode に変換するコストが発生します。

UTF-16 と Windows カーネルの使用

于 2010-03-27T01:07:50.573 に答える
1

データに英語しかないと言っても、おそらく間違っています。私たちは今グローバルな世界にいるので、名前/住所/その他には外国の文字が含まれています. OK、あなたが持っているデータの種類はわかりませんが、一般的には、データの保存とユーザーへのデータの表示の両方で UNICODE をサポートするようにアプリケーションを構築すると言えます。これは、GUI を実行するときに Windows 呼び出しの保存と UNICODE バージョンに UTF-8 で XML を使用することをお勧めします。また、Windows GUI は各トークンが 16 ビットである UTF-16 を使用するため、アプリケーション内のデータを 16 ビット幅の文字列で格納することをお勧めします。そして、Windows用のコンパイラには、この目的のために std::wstring が16ビットとして含まれていると思います。

そのため、UTF-16 と UTF-8 の間で多くの変換を行う必要があります。たとえばICUなどの既存のライブラリでそれを行います。

于 2010-03-27T02:03:46.317 に答える