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

How to write UTF-8 file with fprintf in C++

本文关键字:fprintf 编写 UTF-8 文件 C++      更新时间:2023-10-16

我(偶尔)使用Visual Studio和MFC在C++中编程。我用fopen和fprintf写了一个文件。该文件应使用UTF8进行编码。有可能这样做吗?无论我尝试什么,该文件要么是双字节unicode,要么是ISO-8859-2(latin2)编码。

Glanebridge

如果您只想使用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,"%sn",utf8_string.c_str());
}

将程序保存为带有签名的UTF-8或UTF-16(即不要使用没有签名的UTF-8,否则VS将不会生成正确的字符串文本)。程序编写的文件将包含该字符串的UTF-8版本。或者你可以做:

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

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

对于向文件中写入窄字符的任何其他API,基本上都可以执行相同的操作,但请注意,这些方法都不适用于向Windows控制台写入UTF-8。因为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"%sn",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";
    }
}

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

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

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

理论上,您应该简单地设置一个使用UTF-8作为外部编码的区域设置。我的理解是——我不是Windows程序员——Windows没有这样的区域设置,所以你必须求助于特定于实现的方法或非标准库(Dave评论中的链接)。