如何使用fwprintf以UTF-8格式保存文件

3

朋友们,

我是一个c++初学者,正在使用vc 6.0编写一个utf-8编码的文件。

我正在使用fwprintf()函数来完成此操作,但文件仍然以ANSI编码保存。有没有人能告诉我如何使用fwprintf()将文件保存为utf-8编码呢?

以下是我的代码:

#include "stdafx.h"
#include "wchar.h"
#include "windows.h"
int main(int argc, char* argv[])
{
    FILE *file;
    file = fopen ("abc.txt","w");
    fwprintf(file, L"This is my utf-8 encoded file");
    fclose(file);
    WinExec("\"C:\\Program Files\\EditPlus 3\\editplus.exe\abc.txt", SW_SHOWNORMAL);

    return 0;
}

VC 6太老了,已经过时了。如果你能使用一些现代版本(如VS2005、2008、2010、2013),那么请尽管使用它。 - Dialecticus
亲爱的朋友们, 感谢您们宝贵的帮助,但我仍然无法解决问题,因为我正在使用C风格程序来解决它,而且我在vc6.0中。我了解到了函数_wfopen(),但它似乎也不能以utf-8模式创建文件。如果您能至少确认一次vc6中没有api可以做到这一点,我将尝试在vc++ 6.0中重写我的整个代码。期待您的回复,谢谢。 - user3587879
Remy Lebeau 的第一个代码示例使用的是 C,所以这正是你想要的。Remy 的回答非常完整,没有任何回复能够增加其价值。你应该接受那个答案,并使用那段代码。 - Dialecticus
并且需要确认的是:VC6默认不支持UTF-8。您需要额外的代码,可以是您自己编写的,也可以来自其他库。 - Dialecticus
2个回答

3

fopen()在VC6中不支持编码,因此您将需要在代码中手动管理编码,例如:

#include "stdafx.h"
#include "wchar.h"
#include "windows.h"

bool writeUtf8StrToFile(FILE *file, const wchar_t *str)
{
    if (!file) return false;
    int wlen = lstrlenW(str);
    if (wlen == 0) return true;
    int utf8len = WideCharToMultiByte(CP_UTF8, 0, str, wlen, NULL, 0, NULL, NULL);
    if (utf8len == 0) return false;
    char *utf8 = (char*) malloc(utf8len);
    if (!utf8) return false;
    utf8len = WideCharToMultiByte(CP_UTF8, 0, str, wlen, utf8, utf8len, NULL, NULL);
    if (utf8len == 0) return false;
    fwrite(utf8, 1, utf8len, file);
    free(utf8);
    return true;
}

int main(int argc, char* argv[])
{
    FILE *file = fopen ("abc.txt", "wb");
    if (file)
    {
        writeUtf8StrToFile(file, L"This is my utf-8 encoded file");
        fclose(file);
        WinExec("\"C:\\Program Files\\EditPlus 3\\editplus.exe\" abc.txt", SW_SHOWNORMAL);
    }
    return 0;
}

另一种方法(因为您说您正在使用 C++,而不是上面代码中的 C):

#include "stdafx.h"
#include "wchar.h"
#include "windows.h"
#include <fstream>
#include <string>

bool writeUtf8StrToFile(std::ofstream &file, const std::wstring &str)
{
{
    if (!file.is_open()) return false;
    if (str.empty()) return true;
    int utf8len = WideCharToMultiByte(CP_UTF8, 0, str.c_str(), str.length(), NULL, 0, NULL, NULL);
    if (utf8len == 0) return false;
    std::string utf8(utf8len, '\0');
    WideCharToMultiByte(CP_UTF8, 0, str.c_str(), str.length(), &utf8[0], utf8len, NULL, NULL);
    file << utf8;
    return true;
}

int main(int argc, char* argv[])
{
    std::ofstream file("abc.txt", std::ios::out | std::ios::binary);
    if (file.is_open())
    {
        writeUtf8StrToFile(file, L"This is my utf-8 encoded file");
        file.close();
        WinExec("\"C:\\Program Files\\EditPlus 3\\editplus.exe\" abc.txt", SW_SHOWNORMAL);
    }    
    return 0;
}

或者,您可以使用来自这篇文章的UTF-8库,例如:

#include "stdafx.h"
#include "wchar.h"
#include "windows.h"
#include <fstream>
#include <string>
#include <iterator>
#include "utf8.h"

int main(int argc, char* argv[])
{
    std::ofstream file("abc.txt", std::ios::out | std::ios::binary);
    if (file.is_open())
    {
        std::wstring utf16str = L"This is my utf-8 encoded file";
        std::string utf8str;
        utf8::utf16to8(utf16str.begin(), utf16str.end(), std::back_inserter(utf8str));
        file << utf8str;
        file.close();
        WinExec("\"C:\\Program Files\\EditPlus 3\\editplus.exe\" abc.txt", SW_SHOWNORMAL);
    }    
    return 0;
}

或者,使用这篇文章中的UTF-8流转换器,例如:

#include "stdafx.h"
#include "wchar.h"
#include "windows.h"
#include <fstream>
#include "stxutif.h"

int main(int argc, char* argv[])
{
    std::wofstream fs("abc.txt", std::ios::out);
    if (file.is_open())
    {
        std::locale utf8_locale(std::locale(), new utf8cvt<false>);
        file.imbue(utf8_locale); 
        file << L"This is my utf-8 encoded file";
        file.close();
        WinExec("\"C:\\Program Files\\EditPlus 3\\editplus.exe\" abc.txt", SW_SHOWNORMAL);
    }    
    return 0;
}

2

如果您的编译器允许,您可以在fopen调用中将"w"替换为"w,ccs=UTF-8"


这在VC6上不起作用;支持UNICODE、UTF-8和UTF16-LE的流编码的fopen直到VC 2005才出现。 - Colin Robertson
这个编译器已经有将近10年的历史了。为什么一个新手程序员会使用一个旧的编译器呢? - Dialecticus
我自己也在想这个问题。你可以从MSDN免费获取最新的VC工具集,它具有更多的操作系统兼容性和标准合规性。我建议使用Visual Studio Express 2013 for Windows Desktop套件来编写控制台程序。VC6追溯到1998年,对于Windows 2000/XP及以后的任何事情都没有什么用处。 - Colin Robertson
我使用了_wfopen(),但仍然无法做到这一点。这是msdn参考链接,有人能给我一段在C中工作而不是cpp的代码吗?http://msdn.microsoft.com/en-us/library/aa246392%28v=vs.60%29.aspx - user3587879
@user3587879 抱歉,我没有注意到你正在使用VC6。我的答案对VC6无效。 - Dialecticus
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接