12

私は現在、任意のウィンドウでGetWindowTextを呼び出し、後で処理するためにそのデータをファイルに保存する必要があるアプリケーションを作成しています。簡単に言うと、バトルフィールド3でツールが失敗していることに気付き、ウィンドウタイトルの次の文字に問題を絞り込みました: http://www.fileformat.info/info/unicode/char/2122/index。 htm

そこで、次のことを実行する小さなテストアプリを作成しました。

std::wcout << L"\u2122";

低く、プログラムの残りの部分でコンソールウィンドウへの出力が途切れるのを見てください。

MessageBoxWなどのAPIが問題なく表示するのに、なぜMSVC STLがこの文字(および他の文字を想定)を窒息させるのですか?

これらの文字をファイルに印刷するにはどうすればよいですか?

Windows7x64のVC10とVC11の両方でテストされています。

ポストの構成が不十分で申し訳ありませんが、ここで髪を引き裂いています。

ありがとう。

編集:

最小限のテストケース

#include <fstream>
#include <iostream>

int main()
{
  {
    std::wofstream test_file("test.txt");
    test_file << L"\u2122";
  }

  std::wcout << L"\u2122";
}

期待される結果:「™」文字がコンソールとファイルに出力されます。観察結果:ファイルは作成されましたが、空です。コンソールへの出力はありません。

コンソールに使用しているフォントが問題の文字を表示できることを確認しました。ファイルは完全に空です(サイズは0バイト)。

編集:

さらにデバッグすると、「failbit」と「badbit」がストリームに設定されていることがわかります。

編集:

また、Boost.Localeを使用してみましたが、すべての標準ストリームにグローバルかつ明示的に組み込まれた新しいロケールでも同じ問題が発生しています。

4

4 に答える 4

20

ファイルに書き込むには、ロケールを正しく設定する必要があります。たとえば、UTF-8 文字として書き込みたい場合は、次のように追加する必要があります。

const std::locale utf8_locale
            = std::locale(std::locale(), new std::codecvt_utf8<wchar_t>());
test_file.imbue(utf8_locale);

これら2つのインクルードファイルを追加する必要があります

#include <codecvt>
#include <locale>

コンソールに書き込むには、コンソールを正しいモードに設定する必要があります (これは Windows 固有です)。

_setmode(_fileno(stdout), _O_U8TEXT);

(UTF-8 を使用する場合)。

このためには、次の 2 つのインクルード ファイルを追加する必要があります。

#include <fcntl.h>
#include <io.h>

さらに、Unicode をサポートするフォント (Lucida Console など) を使用していることを確認する必要があります。コンソール ウィンドウのプロパティでフォントを変更できます。

完全なプログラムは次のようになります。

#include <fstream>
#include <iostream>
#include <codecvt>
#include <locale>
#include <fcntl.h>
#include <io.h>

int main()
{

  const std::locale utf8_locale = std::locale(std::locale(),
                                    new std::codecvt_utf8<wchar_t>());
  {
    std::wofstream test_file("c:\\temp\\test.txt");
    test_file.imbue(utf8_locale);
    test_file << L"\u2122";
  }

  _setmode(_fileno(stdout), _O_U8TEXT);
  std::wcout << L"\u2122";
}
于 2012-03-26T09:02:40.253 に答える
2

いつも使っていstd::wcoutますか、それとも時々使っていstd::coutますか? これらを混ぜてもうまくいきません。もちろん、エラーの説明「窒息」は、観察している問題をまったく示していません。ただし、これはファイルを使用する問題とは別の問題だと思います。

問題の実際の説明がないため、問題を解決するには、水晶玉に続いて暗闇の中でショットが必要です...ファイルからUnicode文字を取得したいので、使用しているファイルストリームが使用していることを確認してくださいファセットが実際に適切な Unicode エンコーディングに変換されるstd::localeです。std::codecvt<...>

于 2012-03-25T11:18:53.420 に答える
2

GCC (バージョン 4.4 から 4.7) と MSVC 10 をテストしたところ、すべてこの問題が発生します。

同様に壊れているのはwprintfで、これは C++ ストリーム API と同じくらいしか機能しません。

また、未加工の Win32 API をテストして、失敗の原因が他にないかどうかを確認しました。これは機能します。

#include <windows.h>
int main()
{ 
    HANDLE stdout = GetStdHandle(STD_OUTPUT_HANDLE);
    DWORD n;
    WriteConsoleW( stdout, L"\u03B2", 1, &n, NULL );
}

これはコンソールに書き込みβます(cmdのフォントをLucida Consoleのようなものに設定した場合)。

結論:wchar_t大規模な C++ 標準ライブラリの両方の実装で、出力がひどく壊れています。

于 2012-03-25T13:31:55.577 に答える
1

ワイド文字ストリームは入力としてUnicodeを取りますが、それは出力として生成されるものではありません。文字は変換されます。変換先のエンコーディングで文字を表現できない場合、出力は失敗します。

于 2012-03-25T17:09:58.183 に答える