【问题标题】:Wrote to a file using std::wofstream. The file remained empty使用 std::wofstream 写入文件。该文件仍然是空的
【发布时间】:2011-04-26 10:17:50
【问题描述】:

我使用VS2008编写了以下程序:

#include <fstream>
int main()
{
    std::wofstream fout("myfile");
    fout << L"Հայաստան Россия Österreich Ελλάδα भारत" << std::endl;
}

当我尝试编译它时,IDE 询问我是否想以 unicode 格式保存我的源文件,我说“是的,请”。
然后我运行程序,myfile 出现在我的项目文件夹中。我用记事本打开它,文件是空的。我记得记事本只支持 ASCII 数据。我用写字板打开它,它仍然是空的。最后,我内心的小天才敦促我查看文件大小,毫不奇怪它是 0 字节。所以我重建并重新运行程序,没有效果。最后,我决定在 StackOverflow 上向非常聪明的人询问我缺少什么,我在这里:)

已编辑:

在上述聪明人留下一些cmets之后,我决定听从他们的建议,将程序改写成这样:

#include <fstream>
#include <iostream>
int main()
{
    std::wofstream fout("myfile");
    if(!fout.is_open())
    {
        std::cout << "Before: Not open...\n";
    }
    fout << L"Հայաստան Россия Österreich Ελλάδα भारत" << std::endl;
    if(!fout.good())
    {
        std::cout << "After: Not good...\n";
    }
}

建造它。跑了。而且......控制台清楚地显示,令我惊讶的是:“之后:不好......”。 所以我编辑了我的帖子以提供新信息,并开始等待答案来解释为什么会这样以及我能做什么。 :)

【问题讨论】:

  • 请随时重新标记我的问题,因为我不完全确定标签是否正确
  • 首先,检查 fout.good()
  • 检查 fout 是否有效(听起来像,但最好检查代码)。
  • @Martin:在我写之前还是之后?
  • @Xirdus:不,不要。在 after 操作之前不会设置状态位。而是检查is_open

标签: c++ windows visual-studio encoding wofstream


【解决方案1】:

在 Visual Studio 中,输出流始终以 ANSI 编码编写,并且不支持 UTF-8 输出。

基本上需要做的是创建一个语言环境类,在其中安装 UTF-8 facet,然后将其灌输到 fstream。

代码点未转换为 UTF 编码会发生什么情况。所以基本上这在 MSVC 下是行不通的,因为它不支持 UTF-8。

这适用于具有 UTF-8 语言环境的 Linux

#include <fstream>
int main()
{
    std::locale::global(std::locale(""));
    std::wofstream fout("myfile");
    fout << L"Հայաստան Россия Österreich Ελλάδα भारत" << std::endl;
}

~ 在 Windows 下这会起作用:

#include <fstream>
int main()
{
    std::locale::global(std::locale("Russian_Russia"));
    std::wofstream fout("myfile");
    fout << L"Россия" << std::endl;
}

因为 MSVC 仅支持 ANSI 编码。

Codecvt facet 可以在一些 Boost 库中找到。例如:http://www.boost.org/doc/libs/1_38_0/libs/serialization/doc/codecvt.html

【讨论】:

  • 非常感谢。但是,如果我确实希望它打印整个字符串怎么办?有什么解决方法吗?
  • 是的,安装 utf-8 codecvt facet。 Boost 中有这样的现成方面。还有 Boost.Locale 库,但最后一个可能有点矫枉过正。
  • 这仍然是 C++14 和 VS2015 的最佳方式吗?
【解决方案2】:

MSVC 为这个问题提供了codecvt_utf8 语言环境方面。

#include <codecvt>

// ...  
std::wofstream fout(fileName);
std::locale loc(std::locale::classic(), new std::codecvt_utf8<wchar_t>);
fout.imbue(loc);

【讨论】:

  • @DerKuchen:致命错误 C1083:无法打开包含文件:'codecvt':没有这样的文件或目录。
  • @Armen Tsirunyan:你使用什么版本的 MSVC?至少对于 MSVC 2010 来说它是有效的。
  • @DerKuchen:正如我的帖子所说,我使用的是 MSVC2008。所以你是在暗示我不能用我的编译器做我想做的事吗? :(
  • @Armen Tsirunyan:对不起,我忽略了这一点。我用MSVC2008试了一下,好像这​​个版本漏掉了header。
  • 我发现我可以下载 标头,但我找不到它可供下载...如果可能/合法的话,有什么想法吗?好吧,不管我不关心法律:)
【解决方案3】:

我发现以下代码工作正常。我正在使用 VS2019。

#include <iostream>
#include <fstream>
#include <codecvt>

int main()
{
    std::wstring str = L"abàdëef€hhhhhhhµa";
    std::wofstream fout(L"C:\\app.log.txt", ios_base::app); //change this to ios_base::in or ios_base::out as per relevance
    std::locale loc(std::locale::classic(), new std::codecvt_utf8<wchar_t>);
    fout.imbue(loc);
    fout << str;
    fout.close();
}

【讨论】:

  • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
猜你喜欢
  • 2016-12-23
  • 1970-01-01
  • 2021-08-23
  • 2022-08-19
  • 1970-01-01
  • 1970-01-01
  • 2016-05-19
  • 1970-01-01
相关资源
最近更新 更多