WideCharToMultiByte 函数 (stringapiset.h)

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

谨慎 错误地使用 WideCharToMultiByte 函数可能会危及应用程序的安全性。 调用此函数很容易导致缓冲区溢出,因为 lpWideCharStr 指示的输入缓冲区的大小等于 Unicode 字符串中的字符数,而 lpMultiByteStr 指示的输出缓冲区的大小等于字节数。 若要避免缓冲区溢出,应用程序必须指定适合缓冲区接收的数据类型的缓冲区大小。

从 UTF-16 转换为非 Unicode 编码的数据可能会丢失数据,因为代码页可能无法表示特定 Unicode 数据中使用的每个字符。 有关详细信息,请参阅 安全注意事项:国际功能

 
注意 ANSI 代码页在不同计算机上可能不同,也可以针对单个计算机进行更改,从而导致数据损坏。 为了获得最一致的结果,应用程序应使用 Unicode(例如 UTF-8 或 UTF-16),而不是特定的代码页,除非旧标准或数据格式阻止使用 Unicode。 如果无法使用 Unicode,则当协议允许时,应用程序应使用适当的编码名称来标记数据流。 HTML 和 XML 文件允许标记,但文本文件不允许。
 

语法

int WideCharToMultiByte(
  [in]            UINT                               CodePage,
  [in]            DWORD                              dwFlags,
  [in]            _In_NLS_string_(cchWideChar)LPCWCH lpWideCharStr,
  [in]            int                                cchWideChar,
  [out, optional] LPSTR                              lpMultiByteStr,
  [in]            int                                cbMultiByte,
  [in, optional]  LPCCH                              lpDefaultChar,
  [out, optional] LPBOOL                             lpUsedDefaultChar
);

参数

[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
Windows 2000: 符号代码页 (42) 。
CP_THREAD_ACP
Windows 2000: 当前线程的 Windows ANSI 代码页。
注意 此值在不同计算机上可能不同,即使在同一网络上也是如此。 可以在同一台计算机上对其进行更改,导致存储的数据无法恢复地损坏。 此值仅用于临时使用,永久存储应尽可能使用 UTF-16 或 UTF-8。
 
CP_UTF7
UTF-7。 仅当受 7 位传输机制强制使用此值。 最好使用 UTF-8。 设置此值后, 必须将 lpDefaultCharlpUsedDefaultChar 设置为 NULL
CP_UTF8
UTF-8。 设置此值后, 必须将 lpDefaultCharlpUsedDefaultChar 设置为 NULL

[in] dwFlags

指示转换类型的标志。 应用程序可以指定以下值的组合。 当未设置这些标志时,函数的执行速度更快。 应用程序应指定具有特定值WC_DEFAULTCHAR WC_NO_BEST_FIT_CHARS和WC_COMPOSITECHECK以检索所有可能的转换结果。 如果未提供所有三个值,将缺少一些结果。

含义
WC_COMPOSITECHECK
转换复合字符,由基字符和非节奏字符组成,每个字符具有不同的字符值。 将这些字符转换为预组合字符,这些字符具有基数-非节奏字符组合的单个字符值。 例如,在字符 è 中,e 是基字符,重音符严重标记是非节奏字符。
注意 Windows 通常表示具有预编译数据的 Unicode 字符串,因此不需要使用 WC_COMPOSITECHECK 标志。
 

应用程序可以将WC_COMPOSITECHECK与以下任意一个标志组合在一起,默认值为WC_SEPCHARS。 当 Unicode 字符串中基本-非节奏字符组合的预编译映射不可用时,这些标志确定函数的行为。 如果未提供这些标志,则函数的行为就像设置WC_SEPCHARS标志一样。 有关详细信息,请参阅 “备注 ”部分中的WC_COMPOSITECHECK和相关标志。

WC_DEFAULTCHAR 将异常替换为转换过程中的默认字符。
WC_DISCARDNS 在转换期间放弃非节奏字符。
WC_SEPCHARS 默认。 在转换期间生成单独的字符。
 
WC_ERR_INVALID_CHARS
Windows Vista 及更高版本: 如果遇到无效的输入字符,则返回 0 并将最后一个错误代码设置为ERROR_NO_UNICODE_TRANSLATION) , (失败。 可以通过调用 GetLastError 来检索最后一个错误代码。 如果未设置此标志,则函数会将非法序列替换为 U+FFFD (根据指定的代码页) 编码,并通过返回转换后的字符串的长度来成功。 请注意,仅当 CodePage 指定为 CP_UTF8 或 54936 时,此标志才适用。 它不能与其他代码页值一起使用。
WC_NO_BEST_FIT_CHARS
将不直接转换为多字节的 Unicode 字符转换为 lpDefaultChar 指定的默认字符。 换句话说,如果从 Unicode 转换为多字节,然后再次转换回 Unicode 不会生成相同的 Unicode 字符,则函数将使用默认字符。 此标志可以单独使用,也可以与其他定义的标志结合使用。

对于需要验证的字符串(如文件、资源和用户名),应用程序应始终使用 WC_NO_BEST_FIT_CHARS 标志。 此标志可防止函数将字符映射到看起来相似但语义非常不同的字符。 在某些情况下,语义变化可能是极端的。 例如,在某些代码页中,“∞”的符号 (无穷大) 映射到 8 (8 个) 。

 

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

  • 50220
  • 50221
  • 50222
  • 50225
  • 50227
  • 50229
  • 57002 到 57011
  • 65000 (UTF-7)
  • 42 (符号)
注意 对于代码页 65001 (UTF-8) 或代码页 54936 (GB18030、Windows Vista 及更高版本 ) ,dwFlags 必须设置为 0 或 WC_ERR_INVALID_CHARS。 否则,函数将失败并出现ERROR_INVALID_FLAGS。
 

[in] lpWideCharStr

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

[in] cchWideChar

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

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

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

[out, optional] lpMultiByteStr

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

[in] cbMultiByte

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

[in, optional] lpDefaultChar

如果无法在指定的代码页中表示字符,则指向要使用的字符的指针。 如果函数要使用系统默认值,则应用程序会将此参数设置为 NULL 。 若要获取系统默认字符,应用程序可以调用 GetCPInfoGetCPInfoEx 函数。

对于 CodePage 的CP_UTF7和CP_UTF8设置,此参数必须设置为 NULL。 否则,函数将失败并出现ERROR_INVALID_PARAMETER。

[out, optional] lpUsedDefaultChar

指向标志的指针,该标志指示函数是否在转换中使用了默认字符。 如果源字符串中的一个或多个字符无法在指定的代码页中表示,则标志设置为 TRUE 。 否则,标志设置为 FALSE。 此参数可以设置为 NULL

对于 CodePage 的CP_UTF7和CP_UTF8设置,此参数必须设置为 NULL。 否则,函数将失败并出现ERROR_INVALID_PARAMETER。

返回值

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

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

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

注解

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

如果显式指定输入字符串长度而不指定终止 null 字符,则 WideCharToMultiByte 不会对输出字符串执行 null 终止操作。 若要以 null 终止此函数的输出字符串,应用程序应传入 -1 或显式计算输入字符串的终止 null 字符。

如果 cbMultiByte 小于 cchWideChar,此函数会将 cbMultiByte 指定的字符数写入 lpMultiByteStr 指示的缓冲区。 但是,如果 CodePage 设置为 CP_SYMBOL 且 cbMultiByte 小于 cchWideChar, 则函数不会向 lpMultiByteStr 写入任何字符。

lpDefaultCharlpUsedDefaultChar 都设置为 NULL 时,WideCharToMultiByte 函数的运行效率最高。 下表显示了这些参数的四个可能组合的 函数的行为。

lpDefaultChar lpUsedDefaultChar 结果
NULL NULL 无默认检查。 这些参数设置是用于此函数的最有效参数设置。
非 null 字符 NULL 使用指定的默认字符,但不设置 lpUsedDefaultChar
NULL 非 null 字符 使用系统默认字符并设置 lpUsedDefaultChar (如有必要)。
非 null 字符 非 null 字符 使用指定的默认字符并设置 lpUsedDefaultChar (如有必要)。

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

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

WC_COMPOSITECHECK和相关标志

使用 Unicode 规范化表示字符串中所述,Unicode 允许同一字符串的多个表示形式 (语言) 解释。 例如,具有二元 (元) 的大写字母 A 可以预编译为单个 Unicode 码位“Ä” (U+00C4) 或分解为大写 A 和组合二元字符 (“A”+ “ー”的组合,即 U+0041 U+0308) 。 但是,大多数代码页仅提供组合字符。

WC_COMPOSITECHECK 标志会导致 WideCharToMultiByte 函数测试分解的 Unicode 字符,并尝试在将它们转换为请求的代码页之前对其进行撰写。 此标志仅适用于转换为 单字节 (SBCS) 双字节 (DBCS) 代码页 (代码页 < 50000,不包括代码页 42) 。 如果应用程序需要将分解的 Unicode 数据转换为单字节或双字节代码页,则此标志可能很有用。 但是,并非所有字符都可以通过这种方式转换,并且保存和存储 Unicode 之类的数据更可靠。

当应用程序使用WC_COMPOSITECHECK时,某些字符组合可能仍然不完整,或者可能还剩下其他非节奏字符。 例如,A + 2 + 2 组合到 Ä + 2。 使用 WC_DISCARDNS 标志会导致函数放弃其他非节奏字符。 使用 WC_DEFAULTCHAR 标志会导致函数使用默认替换字符 (通常为“?”请改为 ) 。 使用 WC_SEPCHARS 标志会导致函数尝试将每个附加的非节奏字符转换为目标代码页。 通常,此标志还会导致使用替换字符 (“?”) 。 但是,对于代码页 1258 (越南语) 和 20269,存在且可以使用非节奏字符。 这些代码页的转换并不完美。 某些组合无法正确转换为代码页 1258,并且WC_COMPOSITECHECK会损坏代码页 20269 中的数据。 如前所述,将应用程序设计为保存和存储 Unicode 等数据更为可靠。

示例

ISDSC_STATUS DiscpUnicodeToAnsiSize(
    IN __in PWCHAR UnicodeString,
    OUT ULONG *AnsiSizeInBytes
    )
/*++
Routine Description:
    This routine will return the length needed to represent the unicode
    string as ANSI
Arguments:
    UnicodeString is the unicode string whose ansi length is returned
    *AnsiSizeInBytes is number of bytes needed to represent unicode
        string as ANSI
Return Value:
    ERROR_SUCCESS or error code
--*/
{
    _try
    {
        *AnsiSizeInBytes = WideCharToMultiByte(CP_ACP,
                                               0,
                                               UnicodeString,
                                               -1,
                                               NULL,
                                               0, NULL, NULL);
    } _except(EXCEPTION_EXECUTE_HANDLER) {
        return(ERROR_NOACCESS);
    }
    return((*AnsiSizeInBytes == 0) ? GetLastError() : ERROR_SUCCESS);
}

要求

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

另请参阅

MultiByteToWideChar

Unicode 和字符集函数

Unicode 和字符集

VBS enclave 中可用的 Vertdll API