如何使用C++将Unicode字符串以UTF-8 BOM的格式写入文件?

3

我可以使用ofstream来写UTF-8 BOM文件。我也可以使用wofstream将Unicode字符串写入文件,并使用utf8_locale(codecvt_utf8)进行缓冲。但是,我无法找到如何以UTF-8 BOM编码将Unicode字符串写入文件的方法。


1
utf-8 不需要 BOM - axiac
3
@axiac说:“它并不需要,但可以有所帮助。在理想的世界中,所有文本都应该附带MIME类型。但由于现实并非如此理想,UTF-8文件中的BOM有助于软件猜测编码。” - Steve Jessop
https://dev59.com/83DYa4cB1Zd3GeqPDrts#15914558 - Andrew
2个回答

4

BOM是文件开头的第一个可选字节,用于指定其编码方式。它与std::fstream没有直接关系,因为fstream只是用于读写随机字节/字符的文件流。

在继续编写您的UTF8编码字符串之前,您只需要手动写入BOM即可。

unsigned uint8_t utf8BOM[] = {0xEF,0xBB,0xBF}; 
fileStream.write(utf8BOM,sizeof(utf8BOM));
//write the rest of the utf8 encoded string..

1
如果您正在使用具有UTF-8编码的区域设置的宽流,则只需字符U+FEFF - Steve Jessop
@SteveJessop UTF-16大端序:FE FF 小端序:FF FE - user2249683
3
@Dieter 那就是字节序列。Unicode 码点是(不考虑字节序)U+FEFF - rubenvb
fstream可以将BOM写入文件,但无法像我在问题中提到的那样写入Unicode字符串(例如“日本医疗政策机构”或“Phở”)。 - Alex Huynh
1
FYI:您也可以通过使用“const char utf8Bom [] = u8“\uFEFF””来获取UTF-8 BOM,这是由C ++11编译器实现的。 - Nicol Bolas
为了回应@AlexHuynh的问题,跟随SteveJessop和rubenvb的建议,在打开std::wofstream ofs时,我通过使用"ofs << L"\FEFF";"成功解决了这个问题。 - David Carr

3
以下示例在VS 2015或新的gcc编译器中运行正常:
#include <iostream>
#include <string>
#include <fstream>
#include <codecvt>

int main()
{
    std::string utf8 = u8"日本医療政策機構\nPhở\n";
    std::ofstream f("c:\\test\\ut8.txt");

    unsigned char bom[] = { 0xEF,0xBB,0xBF };
    f.write((char*)bom, sizeof(bom));

    f << utf8;
    return 0;
}

在旧版本的Visual Studio中,您必须声明UTF16字符串(使用L前缀),然后从UTF16转换为UTF8:
#include <iostream>
#include <string>
#include <fstream>
#include <Windows.h>

std::string get_utf8(const std::wstring &wstr)
{
    if (wstr.empty()) return std::string();
    int sz = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), 0, 0, 0, 0);
    std::string res(sz, 0);
    WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), &res[0], sz, 0, 0);
    return res;
}

std::wstring get_utf16(const std::string &str)
{
    if (str.empty()) return std::wstring();
    int sz = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), 0, 0);
    std::wstring res(sz, 0);
    MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &res[0], sz);
    return res;
}

int main()
{
    std::string utf8 = get_utf8(L"日本医療政策機構\nPhở\n");

    std::ofstream f("c:\\test\\ut8.txt");

    unsigned char bom[] = { 0xEF,0xBB,0xBF };
    f.write((char*)bom, sizeof(bom));

    f << utf8;
    return 0;
}

谢谢Barmak。我正在使用Visual Studio 2013,但在“u8”文字上出现错误,因为VS2013无法理解它。我知道它可以在VS2015上工作,但我想在VS2013上做到这一点。 - Alex Huynh
我不记得VS2013的功能。看看更新后的代码,它应该可以在旧的编译器上工作。 - Barmak Shemirani

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