我正在使用 VisualStudio 和 MFC 用 C++ 编程(只是偶尔)。我用 fopen 和 fprintf 写了一个文件。该文件应以 UTF8 编码。有没有可能做到这一点?无论我尝试什么,该文件都是双字节 unicode 或 ISO-8859-2 (latin2) 编码的。
格兰布里奇
可以,但您需要 Visual Studio 2005 或更高版本。然后,您可以使用以下参数调用 fopen:
LPCTSTR strText = "абв";
FILE *f = fopen(pszFilePath, "w,ccs=UTF-8");
_ftprintf(f, _T("%s"), (LPCTSTR) strText);
请记住,这是 Microsoft 扩展,它可能不适用于 gcc 或其他编译器。
如果您只想使用 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,您可以执行基本相同的操作,但请注意,这些方法均不适用于将 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";
}
}
理论上,您应该简单地设置一个使用 UTF-8 作为外部编码的语言环境。我的理解——我不是 Windows 程序员——是Windows 没有这样的语言环境,所以你必须求助于实现特定的方法或非标准库(来自 Dave 的评论的链接)。