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_NO_BEST_FIT_CHARS和WC_COMPOSITECHECK WC_DEFAULTCHAR,以擷取所有可能的轉換結果。 如果未提供這三個值,某些結果將會遺失。

意義
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 規格。 在舊版操作系統上使用的函式會編碼或譯碼 lone Surrogate halves 或不相符的 Surrogate 字組。 以舊版 Windows 撰寫的程式代碼,依賴此行為來編碼隨機非文字二進位數據可能會發生問題。 不過,使用此函式來產生有效 UTF-8 字串串的程式代碼會與舊版 Windows 操作系統的行為相同。

從 Windows 8 開始:WideCharToMultiByte 會在 Stringapiset.h 中宣告。 在 Windows 8 之前,它會在 Winnls.h 中宣告。

WC_COMPOSITECHECK和相關旗標

如同 使用 Unicode 正規化來代表字串中所述,Unicode 允許相同字串的多個表示法 (以語言方式解譯) 。 例如,大寫字母 A (umlaut) 可以預先編譯為單一 Unicode 字碼指標 “Ä” (U+00C4) ,或解譯為大寫 A 和合併 dieresis 字元 (“A” + “ー”,也就是 U+0041 U+0308) 。 不過,大部分的代碼頁只提供撰寫的字元。

WC_COMPOSITECHECK 旗標會導致 WideCharToMultiByte 函式測試已分解的 Unicode 字元,並嘗試撰寫它們,然後再將它們轉換成所要求的代碼頁。 此旗標僅適用於轉換成 單一位元組 (SBCS) 雙位元組 (DBCS) 代碼頁 (代碼頁 < 50000,不包括代碼頁 42) 。 如果您的應用程式必須將分解的 Unicode 資料轉換成單一位元組或雙位元組代碼頁,此旗標可能很有用。 不過,並非所有字元都可以以此方式轉換,而且儲存和儲存 Unicode 這類數據比較可靠。

當應用程式使用WC_COMPOSITECHECK時,某些字元組合可能會維持不完整,或可能會留下額外的非步調字元。 例如,A + Ctrl + Ctrl 結合至 Ä + Ctrl。 使用 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)
程式庫 Kernel32.lib
DLL Kernel32.dll

另請參閱

MultiByteToWideChar

Unicode 和字元集函式

Unicode 和字元集

VBS 記憶體保護區中可用的 Vertdll API