如何在C ++中用fprintf编写UTF-8文件

时间:2012-04-05 12:38:50

标签: c++ utf-8 mfc fopen printf

我使用VisualStudio和MFC在C ++中编程(只是偶然)。我用fopen和fprintf写了一个文件。该文件应以UTF8编码。有没有可能这样做?无论我尝试什么,该文件都是双字节unicode或ISO-8859-2(latin2)编码。

Glanebridge

3 个答案:

答案 0 :(得分:2)

是的,但您需要Visual Studio 2005或更高版本。然后,您可以使用以下参数调用fopen:

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

请记住,这是Microsoft扩展,它可能无法与gcc或其他编译器一起使用。

答案 1 :(得分: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-16的UTF-8(即不使用UTF-8而不签名,否则VS将不会生成正确的字符串文字)。程序写入的文件将包含该字符串的UTF-8版本。或者你可以这样做:

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

在这种情况下,您必须将文件保存为UTF-8 而不使用签名,因为您希望编译器认为源编码与执行编码相同...这有点像一个依赖于编译器,IMO,破坏行为的黑客。

对于将窄字符写入文件,您可以使用任何其他API执行基本相同的操作,但请注意,这些方法都不适用于将UTF-8写入Windows控制台。由于C运行时和/或控制台有点坏,您只能通过执行SetConsoleOutputCP(65001)然后使用puts多种函数之一将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";
    }
}

答案 2 :(得分:1)

理论上,您应该只设置一个使用UTF-8作为外部编码的语言环境。我的理解 - 我不是Windows程序员 - 是Windows has no such locale,因此您必须采用特定于实现的方法或非standard libraries(来自Dave评论的链接)。