【问题标题】:fgetws fails to get the exact wide char string from FILE*fgetws 无法从 FILE* 获取确切的宽字符字符串
【发布时间】:2014-07-19 02:55:43
【问题描述】:

我正在使用 fgetws 从文件中逐行获取一些字符串。我拥有的文件来自一个 popen 命令。这是代码sn-p:

    FILE* pInstalledApps = popen( command.c_str(), "r" );
    if( NULL != pInstalledApps )
    {
        wchar_t currentAppPath [kMaximumAppPathLength];

        // Reading app paths one line at a time.
        while ( ! feof (pInstalledApps) )
        {
            if ( fgetws  ( currentAppPath, kMaximumAppPathLength, pInstalledApps) == NULL )
            {
                break;
            }
            wchar_t *pCharPos = NULL;
            if ( ( pCharPos = wcschr( currentAppPath, L'\n' ) ) != NULL )
            {
                *pCharPos = L'\0';
            }
            std::wstring appPath( currentAppPath );

                            //Do something with the wstring
        }
        pclose( pInstalledApps );
    }

当我得到的字符串 currentAppPath 有宽字符字符串时,我得到的 appPath 没有预期的字符串。例如,如果我从 FILE 获得的字符串是 10teciêênks,我的 appPath 变量将具有 10tecieÌeÌnks

【问题讨论】:

  • 文件中的内容与应用程序期望的内容之间的区域设置/编码不匹配?您是否在应用程序的某处设置编码?
  • @DevSolar 感谢您的回复,这只是项目的一小部分。我不确定语言环境是否设置在某个地方。如果我将字符串作为普通字符串读取,然后使用 boost::locale 将其转换为 wstring,它就可以工作。但我不确定它是否每次都有效。从 char* (可以有widechar)创建std::string时,是否有可能在字符串结束之前遇到空字符?
  • 如果您的输入编码是例如UTF-16,你有空字符。除非您明确设置编码,否则您根本无法假设任何事情。有没有考虑过看看ICU?这可能是您会发现的处理编码的最强大、最稳定和最便携的解决方案。实际上,这就是 boost::locale 所依赖的后端,只是去掉了中介——当您最终在一个分发 Boost 的平台上没有编译 ICU 支持时,这是有益的。;-)

标签: c++ file-io wstring widechar


【解决方案1】:

这看起来像是编码(或更具体地说,解码)问题。宽字符 API 函数不会自动检测数据的字符编码。您需要在应用程序中进行设置,例如:

#include <locale.h>

setlocale(LC_ALL, "en.UTF-8");

fgetws 的手册页指出:

The behavior of fgetws() depends on the LC_CTYPE category of the current locale.

所以使用:

setlocale(LC_CTYPE, "en.UTF-8");

应该也可以。

注意:以上假设数据是 UTF-8 编码的。

更新:可以通过以下方式保留当前语言环境:

char *prev_locale = strdup(setlocale(LC_CTYPE, NULL));
setlocale(LC_CTYPE, "en.UTF-8");
// ...
setlocale(LC_CTYPE, prev_locale);
free(prev_locale);

【讨论】:

  • 是否可以在 fgetws 调用之前将locale 设置为 en.UTF-8,并在使用 fgetws 之后将其设置回之前的 LC_CTYPE 设置。我不确定我的 fgetws 调用之前的设置是什么。我可以以任何方式要求以前的设置吗?
猜你喜欢
  • 1970-01-01
  • 2012-12-03
  • 2016-06-30
  • 1970-01-01
  • 1970-01-01
  • 2012-03-06
  • 1970-01-01
  • 2019-10-27
  • 1970-01-01
相关资源
最近更新 更多