7

VisualStudio と MFC を使用して C++ で (たまに) プログラミングしています。fopen と fprintf でファイルを書き込みます。ファイルは UTF8 でエンコードする必要があります。これを行う可能性はありますか?何を試しても、ファイルは 2 バイトの Unicode または ISO-8859-2 (latin2) でエンコードされています。

グラネブリッジ

4

3 に答える 3

2

fprintfを使用するだけの場合は、ロケールを設定したり、ファイルに特別なモードを設定したりする必要はありません。UTF-8でエンコードされた文字列を使用するだけです。

#include <cstdio>
#include <codecvt>

int main() {
    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>,wchar_t> convert;
    std::string utf8_string = convert.to_bytes(L"кошка 日本国");

    if(FILE *f = fopen("tmp","w"))
        fprintf(f,"%s\n",utf8_string.c_str());
}

プログラムを署名付きのUTF-8またはUTF-16として保存します(つまり、署名なしのUTF-8を使用しないでください。そうしないと、VSは正しい文字列リテラルを生成しません)。プログラムによって作成されたファイルには、その文字列のUTF-8バージョンが含まれます。または、次のことができます。

int main() {
    if(FILE *f = fopen("tmp","w"))
        fprintf(f,"%s\n","кошка 日本国");
}

この場合、ファイルを署名なしでUTF-8として保存する必要があります。これは、ソースエンコーディングが実行エンコーディングと同じであるとコンパイラに認識させたいためです...これは、コンパイラのIMOに依存するちょっとしたハックです。壊れた動作。

ファイルに狭い文字を書き込むための他のAPIでも基本的に同じことを行うことができますが、これらのメソッドはいずれもWindowsコンソールにUTF-8を書き込むためには機能しないことに注意してください。Cランタイムやコンソールが少し壊れているため、SetConsoleOutputCP(65001)を実行してから、putsさまざまな関数の1つを使用することによってのみ、UTF-8をコンソールに直接書き込むことができます。

幅の狭い文字の代わりに幅の広い文字を使用したい場合は、ロケールベースのメソッドとファイル記述子の設定モードが役立ちます。

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

int main() {
    if(FILE *f = fopen("tmp","w")) {
        _setmode(_fileno(f), _O_U8TEXT);
        fwprintf(f,L"%s\n",L"кошка 日本国");
    }
}

#include <fstream>
#include <codecvt>

int main() {
    if(auto f = std::wofstream("tmp")) {
        f.imbue(std::locale(std::locale(),
                new std::codecvt_utf8_utf16<wchar_t>)); // assumes wchar_t is UTF-16
        f << L"кошка 日本国\n";
    }
}
于 2012-04-05T16:42:34.463 に答える
2

はい。ただし、Visual Studio 2005 以降が必要です。次に、パラメーターを指定して fopen を呼び出すことができます。

LPCTSTR strText = "абв";
FILE *f = fopen(pszFilePath, "w,ccs=UTF-8");
_ftprintf(f, _T("%s"),  (LPCTSTR) strText);

これは Microsoft 拡張機能であることを覚えておいてください。おそらく gcc やその他のコンパイラでは動作しません。

于 2012-04-05T13:16:13.483 に答える
1

理論的には、UTF-8 を外部エンコーディングとして使用するロケールを設定する必要があります。私の理解-私はWindowsプログラマーではありません-Windowsにはそのようなロケールがないため、実装固有の手段または非標準ライブラリに頼る必要があります(Daveのコメントからのリンク)。

于 2012-04-05T12:52:39.953 に答える