1

关于这一点有很多关于 SO 的问题,但其中大多数都没有提到将 wstring 写回文件。因此,例如,我发现这是为了阅读:

// open as a byte stream
std::wifstream fin("/testutf16.txt", std::ios::binary);
// apply BOM-sensitive UTF-16 facet
fin.imbue(std::locale(fin.getloc(),
    new std::codecvt_utf16<wchar_t, 0x10ffff, std::consume_header>));
// read  
std::wstring ws;
for(wchar_t c; fin.get(c); )
{
    std::cout << std::showbase << std::hex << c << '\n';
    ws.push_back(c);
}

我尝试了类似的东西来写作:

    std::wofstream wofs("/utf16dump.txt", std::ios::binary);
    wofs.imbue(std::locale(wofs.getloc(),
        new std::codecvt_utf16<wchar_t, 0x10ffff, std::consume_header>));
    wofs << ws;

但它会产生垃圾,(或 Notpad++ 和 vim 无法解释它)。正如标题 Im on Win、本机 C++、VS 2010 中所述。

输入文件:

t€stUTF16✡
test

结果是这样的:

t€stUTF16✡
test

转换为十六进制:

0000000: 7400 ac20 7300 7400 5500 5400 4600 3100  t.. s.t.U.T.F.1.
0000010: 3600 2127 0d00 0a00 7400 6500 7300 7400  6.!'....t.e.s.t.
0000020: 0a                                       
                     ...

vim 正常输出:

t^@¬ s^@t^@U^@T^@F^@1^@6^@!'^M^@ ^@t^@e^@s^@t^@

编辑:我最终使用了 UTF8。Andrei Alexandrescu 说这是最好的编码,所以没有大的损失。:)

4

3 回答 3

3

您的类似代码 - 不是。您删除了std::ios::binary样式,尽管文档

字节流应写入二进制文件;如果写入文本文件,它可能会损坏。

ASCII 模式下的 NL->CRLF 转换不会对 UTF-16 文件做任何漂亮的事情,因为它将插入一个字节 0x0D 而不是两个字节 0x00 0x0D。

于 2012-06-08T15:37:40.927 回答
2

如果您使用C++11标准,这很容易(因为有很多额外的包含"utf8"可以永远解决这个问题)。

但是如果你想使用旧标准的多平台代码,你可以使用这种方法来编写流:

  1. 阅读有关流的 UTF 转换器的文章
  2. stxutif.h从上面的来源 添加到您的项目
  3. 以 ANSI 模式打开文件并将 BOM 添加到文件的开头,如下所示:

    std::ofstream fs;
    fs.open(filepath, std::ios::out|std::ios::binary);
    
    unsigned char smarker[3];
    smarker[0] = 0xEF;
    smarker[1] = 0xBB;
    smarker[2] = 0xBF;
    
    fs << smarker;
    fs.close();
    
  4. 然后打开文件UTF并在那里写下你的内容:

    std::wofstream fs;
    fs.open(filepath, std::ios::out|std::ios::app);
    
    std::locale utf8_locale(std::locale(), new utf8cvt<false>);
    fs.imbue(utf8_locale); 
    
    fs << .. // Write anything you want...
    
于 2012-09-20T17:11:43.330 回答
1

对于输出,您想使用generate_header而不是consume_header.

请参阅http://en.cppreference.com/w/cpp/locale/codecvt_mode

于 2012-06-08T15:44:14.940 回答