【问题标题】:Printing/writing wchar_t?打印/写入 wchar_t?
【发布时间】:2016-10-02 17:54:04
【问题描述】:

首先:我知道 C++ 有类似的主题,但我对标准 C 很好奇,我不相信我的问题与以前的问题有关。

我正在尝试为一个简单的程序实现 Unicode 支持,该程序只要求用户通过文件夹浏览器选择一个目录,然后将其传递给另一个程序(仅到达第一部分)。但是当尝试将接收到的路径写入文件时,会产生一个 0 字节的文件。当使用wprintf_s 打印出来时,非ASCII 字符会作为问号出现。我不相信有任何未定义的行为或任何东西,因为我已经仔细检查了文档。那我做错了什么?

目前的代码如下所示(只是严格测试条件下的最低要求):

#define UNICODE
#define _UNICODE

#include <windows.h>
#include <shlobj.h>
#include <stdio.h>

int main()
{
    BROWSEINFOW bi = { 0 };
    LPITEMIDLIST pidl;
    wchar_t path[MAX_PATH];
    pidl = SHBrowseForFolderW(&bi);
    SHGetPathFromIDListW(pidl, path);
    wprintf_s(L"%s\n", path);
    return 0;
}

上面的代码定期打印它。当尝试写入文件时,我将 wprintf_s 调用替换为这个(当然首先声明了 FILE *f):

if(_wfopen_s(&f, L"C:\\test.txt", L"w"))
{
    fwprintf_s(f, L"%s\n", path)
    fclose(f);
}

但是,我也尝试将fwritewwb 模式一起使用,但所有方法都会导致一个空文件。

【问题讨论】:

  • 试试`_setmode(_fileno(stdout), _O_U16TEXT);`stackoverflow.com/a/36527398/4603670
  • @BarmakShemirani 呵呵。这适用于标准输出,但我仍然得到实际文件的空输出?有什么想法吗?
  • 问题是终端应用或显示输出的应用可能配置不正确。
  • 每当 I/O 函数无法按预期工作时,最好检查函数的返回值。
  • @chux 再次,我检查了文档 - 事实上仔细检查。 wprintf_s 只接受格式字符串和相应的参数,就像常规函数一样。你自己看。但无论如何,stdout 的问题已经解决了。剩下的问题是写入实际文件。

标签: c winapi unicode wchar-t


【解决方案1】:

您需要_O_U16TEXT 用于控制台输出,"UTF-16LE" 用于文件输出。

另外,根据 MS documentation_wfopen_s 在成功时返回零:

如果成功则返回零值;失败的错误代码。见错误号, _doserrno、_sys_errlist 和 _sys_nerr 了解有关这些错误代码的更多信息。

你应该确保返回值为零

if (0 == _wfopen_s(&f, filename, L"w, ccs=UTF-16LE")){
    //isokay ...
}

或检查f 是否为非NULL。例如:

#include <stdio.h>
#include <io.h> //for _setmode
#include <fcntl.h> //for _O_U16TEXT

int main()
{
    _setmode(_fileno(stdout), _O_U16TEXT);
    const wchar_t *buf = L"ελληνική";
    wprintf(L"%s\n", buf);

    FILE *f = NULL;
    _wfopen_s(&f, L"C:\\test\\test.txt", L"w, ccs=UTF-16LE");
    if (f)
    {
        fwprintf_s(f, L"%s\n", buf);
        fclose(f);
    }

    return 0;
}

【讨论】:

  • 做到了!至于检查句柄,我假设,由于_wfopen_s 在错误时返回非零值(例如未能创建句柄?),因此检查就足够了……他们或多或少是如何做到的至少是 MSDN 示例代码(只是,它们将错误分配给变量)。
  • @user966939:upvote-arrow 的工具提示为 “这个答案很有用”。当有人接受一个答案但没有投票时,我总是觉得很奇怪。
  • @IInspectable 好吧,我刚刚注意到他更新了他的答案。我现在意识到(尽管在我之前的评论中我自己提到了_wfopen_s 的返回值)我正在根据代码中的非零数字检查成功,当然成功实际上是 0。我认为 Barmak 在函数返回值的帮助下通过检查句柄错误地指责我犯了错误。所以他当然也值得一分。不过,我认为一件事不一定意味着另一件事。
猜你喜欢
  • 2015-02-11
  • 2010-10-04
  • 2021-04-09
  • 2017-04-05
  • 2020-01-24
  • 2021-11-21
  • 2023-03-20
  • 1970-01-01
  • 2021-10-28
相关资源
最近更新 更多