MultiByteToWideChar 函数 (stringapiset.h)

将字符串映射到 UTF-16(宽字符)字符串。 字符串不一定来自多字节字符集。

警告 错误地使用 MultiByteToWideChar 函数可能会损害应用程序的安全性。 调用此函数很容易导致缓冲区溢出,因为由 lpMultiByteStr 指示的输入缓冲区的大小 等于字符串中的字节数,而由 lpWideCharStr 指示的输出缓冲区的大小 等于字符数。 为了避免缓冲区溢出,应用程序必须指定适合缓冲区接收的数据类型的缓冲区大小。 有关详细信息,请参阅 安全注意事项:国际功能
 
注意 ANSI 代码页在不同计算机上可能有所不同,也可以更改单个计算机,从而导致数据损坏。 对于最一致的结果,应用程序应使用 Unicode(如 UTF-8 或 UTF-16),而不是特定的代码页,除非旧标准或数据格式阻止使用 Unicode。 如果无法使用 Unicode,应用程序应在协议允许时使用适当的编码名称标记数据流。 HTML 和 XML 文件允许标记,但文本文件不允许。
 

语法

int MultiByteToWideChar(
  [in]            UINT                              CodePage,
  [in]            DWORD                             dwFlags,
  [in]            _In_NLS_string_(cbMultiByte)LPCCH lpMultiByteStr,
  [in]            int                               cbMultiByte,
  [out, optional] LPWSTR                            lpWideCharStr,
  [in]            int                               cchWideChar
);

参数

[in] CodePage

用于执行转换的代码页。 此参数可以设置为操作系统中安装或可用的任何代码页的值。 有关代码页的列表,请参阅 代码页标识符。 应用程序还可以指定下表中显示的值之一。

价值 意义
CP_ACP
系统默认的 Windows ANSI 代码页。
注意 此值在不同计算机上可能有所不同,即使在同一网络上也是如此。 它可以在同一台计算机上更改,从而导致存储的数据变得不可恢复的损坏。 此值仅用于临时使用,永久存储应尽可能使用 UTF-16 或 UTF-8。
 
CP_MACCP
当前系统 Macintosh 代码页。
注意 此值在不同计算机上可能有所不同,即使在同一网络上也是如此。 它可以在同一台计算机上更改,从而导致存储的数据变得不可恢复的损坏。 此值仅用于临时使用,永久存储应尽可能使用 UTF-16 或 UTF-8。
 
注意 此值主要用于旧代码中,并且通常不需要,因为新式 Macintosh 计算机使用 Unicode 进行编码。
 
CP_OEMCP
当前系统 OEM 代码页。
注意 此值在不同计算机上可能有所不同,即使在同一网络上也是如此。 它可以在同一台计算机上更改,从而导致存储的数据变得不可恢复的损坏。 此值仅用于临时使用,永久存储应尽可能使用 UTF-16 或 UTF-8。
 
CP_SYMBOL
符号代码页 (42)。
CP_THREAD_ACP
当前线程的 Windows ANSI 代码页。
注意 此值在不同计算机上可能有所不同,即使在同一网络上也是如此。 它可以在同一台计算机上更改,从而导致存储的数据变得不可恢复的损坏。 此值仅用于临时使用,永久存储应尽可能使用 UTF-16 或 UTF-8。
 
CP_UTF7
UTF-7。 仅当由 7 位传输机制强制时,才使用此值。 首选 UTF-8 的使用。
CP_UTF8
UTF-8。

[in] dwFlags

指示转换类型的标志。 应用程序可以指定以下值的组合,MB_PRECOMPOSED为默认值。 MB_PRECOMPOSED和MB_COMPOSITE是相互排斥的。 无论其他标志的状态如何,都可以设置MB_USEGLYPHCHARS和MB_ERR_INVALID_CHARS。

价值 意义
MB_COMPOSITE 始终使用分解字符,即基字符和一个或多个非分步字符各具有不同的代码点值。 例如,Ä 由 A + }表示:拉丁文大写字母 A (U+0041) + 组合分音符 (U+0308)。 请注意,此标志不能用于MB_PRECOMPOSED。
MB_ERR_INVALID_CHARS 如果遇到无效的输入字符,则失败。

从 Windows Vista 开始,如果应用程序未设置此标志,则函数不会删除非法代码点,而是将非法序列替换为 U+FFFD(根据指定的代码页进行编码)。

Windows 2000 SP4 及更高版本,Windows XP: 如果未设置此标志,该函数将无提示删除非法代码点。 GetLastError 调用将返回ERROR_NO_UNICODE_TRANSLATION。
MB_PRECOMPOSED
违约;请勿与MB_COMPOSITE一起使用。 始终使用预编译字符,即具有基字符或非字符组合的单个字符值。 例如,在字符 è 中,e 是基字符,重音严重标记是非节奏字符。 如果为字符定义了单个 Unicode 码位,则应用程序应使用它而不是单独的基字符和非节奏字符。 例如,Ä 由单个 Unicode 码位拉丁文大写字母 A WITH DIAERESIS (U+00C4) 表示。
MB_USEGLYPHCHARS
使用字形字符而不是控制字符。

对于下面列出的代码页,dwFlags 必须设置为 0。 否则,函数将失败并 ERROR_INVALID_FLAGS

  • 50220
  • 50221
  • 50222
  • 50225
  • 50227
  • 50229
  • 57002 到 57011
  • 65000 (UTF-7)
  • 42 (符号)

注意

 对于 UTF-8 或代码页 54936(GB18030,从 Windows Vista 开始),dwFlags 必须设置为 0MB_ERR_INVALID_CHARS。 否则,函数将失败并 ERROR_INVALID_FLAGS

[in] lpMultiByteStr

指向要转换的字符串的指针。

[in] cbMultiByte

lpMultiByteStr 参数指示的字符串的大小(以字节为单位)。 或者,如果字符串以 null 结尾,则可以将此参数设置为 -1。 请注意,如果 cbMultiByte0,则函数将失败。

如果此参数为 -1,则该函数将处理整个输入字符串,包括终止 null 字符。 因此,生成的 Unicode 字符串具有终止 null 字符,函数返回的长度包括此字符。

如果此参数设置为正整数,则函数将完全处理指定的字节数。 如果提供的大小不包括终止 null 字符,则生成的 Unicode 字符串不会以 null 结尾,并且返回的长度不包括此字符。

[out, optional] lpWideCharStr

指向接收转换后的字符串的缓冲区的指针。

[in] cchWideChar

lpWideCharStr指示的缓冲区的大小(以字符为单位)。 如果此值 0,则该函数将返回所需的缓冲区大小(以字符为单位,包括任何终止 null 字符)并且不使用 lpWideCharStr 缓冲区。

返回值

返回写入缓冲区的字符数,lpWideCharStr(如果成功)。 如果函数成功,cchWideChar0,则返回值是 lpWideCharStr指示的缓冲区所需的大小(以字符为单位)。 另请参阅 dwFlags,了解输入无效序列时 MB_ERR_INVALID_CHARS 标志如何影响返回值的信息。

如果函数不成功,则返回 0。 若要获取扩展的错误信息,应用程序可以调用 GetLastError,这会返回以下错误代码之一:

  • ERROR_INSUFFICIENT_BUFFER:提供的缓冲区大小不够大,或者错误地设置为 NULL
  • ERROR_INVALID_FLAGS:为标志提供的值无效。
  • ERROR_INVALID_PARAMETER:任何参数值都无效。
  • ERROR_NO_UNICODE_TRANSLATION:在字符串中找到无效的 Unicode。

言论

此函数的默认行为是转换为输入字符串的预编译形式。 如果预编译的窗体不存在,该函数将尝试转换为复合窗体。

MB_PRECOMPOSED标志的使用对大多数代码页的影响很小,因为大多数输入数据已经组成。 请考虑使用 MultiByteToWideChar转换后调用 NormalizeStringNormalizeString 提供更准确的、标准和一致的数据,而且速度更快。 请注意,对于传递给 NormalizeStringNORM_FORM 枚举,NormalizationC 对应于MB_PRECOMPOSED,NormalizationD 对应于MB_COMPOSITE。

如上述警告中所述,如果未首先调用此函数,则输出缓冲区很容易被过度运行,cchWideChar 设置为 0 以获取所需的大小。 如果使用MB_COMPOSITE标志,则每个输入字符的输出长度可以为三个或更多个字符。

lpMultiByteStrlpWideCharStr 指针不得相同。 如果相同,函数将失败,GetLastError 返回值ERROR_INVALID_PARAMETER。

MultiByteToWideChar 如果未显式指定输入字符串长度而不终止 null 字符,则不会终止输出字符串。 若要为 null 终止此函数的输出字符串,应用程序应传入 -1 或显式计算输入字符串的终止 null 字符。

如果设置了MB_ERR_INVALID_CHARS,并且源字符串中遇到无效字符,则函数将失败。 无效字符为下列字符之一:

  • 不是源字符串中的默认字符的字符,但在未设置MB_ERR_INVALID_CHARS时转换为默认字符。
  • 对于 DBCS 字符串,该字符具有前导字节,但没有有效的尾随字节。

从 Windows Vista 开始,此函数完全符合 UTF-8 和 UTF-16 的 Unicode 4.1 规范。 在早期操作系统上使用的函数对 代理项 一半或不匹配的代理项对进行编码或解码。 在早期版本的 Windows 中编写的代码,依赖于此行为来编码随机的非文本二进制数据可能会遇到问题。 但是,对有效 UTF-8 字符串使用此函数的代码的行为方式与早期 Windows 操作系统相同。

Windows XP: 为防止 UTF-8 字符的非最短格式版本的安全问题,MultiByteToWideChar 删除这些字符。

从 Windows 8 开始 MultiByteToWideCharStringapiset.h中声明。 在 Windows 8 之前,它在 Winnls.h中声明。

代码示例

catch (std::exception e)
{
    // Save in-memory logging buffer to a log file on error.

    ::std::wstring wideWhat;
    if (e.what() != nullptr)
    {
        int convertResult = MultiByteToWideChar(CP_UTF8, 0, e.what(), (int)strlen(e.what()), NULL, 0);
        if (convertResult <= 0)
        {
            wideWhat = L"Exception occurred: Failure to convert its message text using MultiByteToWideChar: convertResult=";
            wideWhat += convertResult.ToString()->Data();
            wideWhat += L"  GetLastError()=";
            wideWhat += GetLastError().ToString()->Data();
        }
        else
        {
            wideWhat.resize(convertResult + 10);
            convertResult = MultiByteToWideChar(CP_UTF8, 0, e.what(), (int)strlen(e.what()), &wideWhat[0], (int)wideWhat.size());
            if (convertResult <= 0)
            {
                wideWhat = L"Exception occurred: Failure to convert its message text using MultiByteToWideChar: convertResult=";
                wideWhat += convertResult.ToString()->Data();
                wideWhat += L"  GetLastError()=";
                wideWhat += GetLastError().ToString()->Data();
            }
            else
            {
                wideWhat.insert(0, L"Exception occurred: ");
            }
        }
    }
    else
    {
        wideWhat = L"Exception occurred: Unknown.";
    }

    Platform::String^ errorMessage = ref new Platform::String(wideWhat.c_str());
    // The session added the channel at level Warning. Log the message at
    // level Error which is above (more critical than) Warning, which
    // means it will actually get logged.
    _channel->LogMessage(errorMessage, LoggingLevel::Error);
    SaveLogInMemoryToFileAsync().then([=](StorageFile^ logFile) {
        _logFileGeneratedCount++;
        StatusChanged(this, ref new LoggingScenarioEventArgs(LoggingScenarioEventType::LogFileGenerated, logFile->Path->Data()));
    }).wait();
}

GitHub 上 Windows 通用示例 的示例。

要求

要求 价值
最低支持的客户端 Windows 2000 Professional [桌面应用 |UWP 应用]
支持的最低服务器 Windows 2000 Server [桌面应用 |UWP 应用]
目标平台 窗户
标头 stringapiset.h (包括 Windows.h)
Kernel32.lib
DLL Kernel32.dll

另请参阅

Unicode 和字符集函数

Unicode 和字符集

WideCharToMultiByte

VBS enclave 中提供的 Vertdll API