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) + 组合 DIAERESIS (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 提供更准确、更标准、更一致的数据,还可以更快。 请注意,对于传递给 NormalizeString的NORM_FORM枚举,NormalizationC 对应于 MB_PRECOMPOSED,NormalizationD 对应于MB_COMPOSITE。

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

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

如果显式指定输入字符串长度且未终止 null 字符,则 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 操作系统上的行为方式相同。

Windowsxp: 为了防止 UTF-8 字符的非最短版本出现安全问题, MultiByteToWideChar 会删除这些字符。

从 Windows 8 开始:MultiByteToWideChar 在 中Stringapiset.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 专业版 [桌面应用 |UWP 应用]
最低受支持的服务器 Windows 2000 Server [桌面应用 |UWP 应用]
目标平台 Windows
标头 stringapiset.h (包括 Windows.h)
Library Kernel32.lib
DLL Kernel32.dll

另请参阅

Unicode 和字符集函数

Unicode 和字符集

WideCharToMultiByte

VBS enclave 中可用的 Vertdll API