[英]Conversion from ASCII to Unicode char code (FreeType2)
我在我的一個項目中使用FreeType2。 為了呈現一個字母,我需要提供一個Unicode雙字節字符代碼。 但代碼讀取的字符代碼是ASCII單字節格式。 對於低於128的字符代碼(字符代碼相同),它沒有問題,但是其他128不匹配。 例如:
ASCII中的'a'是0x61,Unicode中的'a'是0x0061 - 這很好
ASCII中的'±'是0xB9,Unicode中的'±'是0x0105 - 完全不同
我試圖在那里使用WinAPI函數,但我一定是做錯了。 這是一個示例:
unsigned char szTest1[] = "ąółź"; //ASCII format
wchar_t* wszTest2;
int size = MultiByteToWideChar(CP_UTF8, 0, (char*)szTest1, 4, NULL, 0);
printf("size = %d\n", size);
wszTest2 = new wchar_t[size];
MultiByteToWideChar(CP_UTF8, 0, (char*)szTest1, 4, wszTest2, size);
printf("HEX: %x\n", wszTest2[0]);
delete[] wszTest2;
我期待創建一個新的寬字符串,最后沒有NULL。 variable always equals 0. Any idea what I'm doing wrong? 但是, 變量總是等於0.任何想法我做錯了什么? 或者也許有一種更簡單的方法來解決問題?
“純”ASCII字符集限制在0-127(7位)范圍內。 具有最高有效位設置的8位字符(即范圍128-255中的那些)不是唯一定義的:它們的定義取決於代碼頁 。 所以,你的性格ą
( 與反尾形符拉丁小寫字母A)由值表示0xB9
在一個特定的代碼頁,這應該是Windows的1250 。 在其他代碼頁中,值0xB9
與不同的字符相關聯(例如,在Windows 1252代碼頁中 , 0xB9
與字符¹
相關聯,即上標數字1)。
要使用Windows Win32 API將字符從特定代碼頁轉換為Unicode UTF-16,可以使用MultiByteToWideChar
,指定正確的代碼頁( 不是 CP_UTF8
如問題代碼中所寫;實際上, CP_UTF8
標識Unicode UTF -8)。 您可能要嘗試將1250
(ANSI中歐;中歐(Windows))指定為正確的代碼頁標識符 。
如果您可以在代碼中訪問ATL ,則可以使用ATL字符串轉換助手類(例如CA2W
的便利性,它將MultiByteToWideChar(
)調用和內存分配包裝在RAII類中; 例如:
#include <atlconv.h> // ATL String Conversion Helpers
// 'test' is a Unicode UTF-16 string.
// Conversion is done from code-page 1250
// (ANSI Central European; Central European (Windows))
CA2W test("ąółź", 1250);
現在,您應該能夠在Unicode API中使用test
字符串。
如果您無法訪問ATL或想要基於C ++ STL的解決方案,您可能需要考慮以下代碼:
///////////////////////////////////////////////////////////////////////////////
//
// Modern STL-based C++ wrapper to Win32's MultiByteToWideChar() C API.
//
// (based on http://code.msdn.microsoft.com/windowsdesktop/C-UTF-8-Conversion-Helpers-22c0a664)
//
///////////////////////////////////////////////////////////////////////////////
#include <exception> // for std::exception
#include <iostream> // for std::cout
#include <ostream> // for std::endl
#include <stdexcept> // for std::runtime_error
#include <string> // for std::string and std::wstring
#include <Windows.h> // Win32 Platform SDK
//-----------------------------------------------------------------------------
// Define an exception class for string conversion error.
//-----------------------------------------------------------------------------
class StringConversionException
: public std::runtime_error
{
public:
// Creates exception with error message and error code.
StringConversionException(const char* message, DWORD error)
: std::runtime_error(message)
, m_error(error)
{}
// Creates exception with error message and error code.
StringConversionException(const std::string& message, DWORD error)
: std::runtime_error(message)
, m_error(error)
{}
// Windows error code.
DWORD Error() const
{
return m_error;
}
private:
DWORD m_error;
};
//-----------------------------------------------------------------------------
// Converts an ANSI/MBCS string to Unicode UTF-16.
// Wraps MultiByteToWideChar() using modern C++ and STL.
// Throws a StringConversionException on error.
//-----------------------------------------------------------------------------
std::wstring ConvertToUTF16(const std::string & source, const UINT codePage)
{
// Fail if an invalid input character is encountered
static const DWORD conversionFlags = MB_ERR_INVALID_CHARS;
// Require size for destination string
const int utf16Length = ::MultiByteToWideChar(
codePage, // code page for the conversion
conversionFlags, // flags
source.c_str(), // source string
source.length(), // length (in chars) of source string
NULL, // unused - no conversion done in this step
0 // request size of destination buffer, in wchar_t's
);
if (utf16Length == 0)
{
const DWORD error = ::GetLastError();
throw StringConversionException(
"MultiByteToWideChar() failed: Can't get length of destination UTF-16 string.",
error);
}
// Allocate room for destination string
std::wstring utf16Text;
utf16Text.resize(utf16Length);
// Convert to Unicode UTF-16
if ( ! ::MultiByteToWideChar(
codePage, // code page for conversion
0, // validation was done in previous call
source.c_str(), // source string
source.length(), // length (in chars) of source string
&utf16Text[0], // destination buffer
utf16Text.length() // size of destination buffer, in wchar_t's
))
{
const DWORD error = ::GetLastError();
throw StringConversionException(
"MultiByteToWideChar() failed: Can't convert to UTF-16 string.",
error);
}
return utf16Text;
}
//-----------------------------------------------------------------------------
// Test.
//-----------------------------------------------------------------------------
int main()
{
// Error codes
static const int exitOk = 0;
static const int exitError = 1;
try
{
// Test input string:
//
// ą - LATIN SMALL LETTER A WITH OGONEK
std::string inText("x - LATIN SMALL LETTER A WITH OGONEK");
inText[0] = 0xB9;
// ANSI Central European; Central European (Windows) code page
static const UINT codePage = 1250;
// Convert to Unicode UTF-16
const std::wstring utf16Text = ConvertToUTF16(inText, codePage);
// Verify conversion.
// ą - LATIN SMALL LETTER A WITH OGONEK
// --> Unicode UTF-16 0x0105
// http://www.fileformat.info/info/unicode/char/105/index.htm
if (utf16Text[0] != 0x0105)
{
throw std::runtime_error("Wrong conversion.");
}
std::cout << "All right." << std::endl;
}
catch (const StringConversionException& e)
{
std::cerr << "*** ERROR:\n";
std::cerr << e.what() << "\n";
std::cerr << "Error code = " << e.Error();
std::cerr << std::endl;
return exitError;
}
catch (const std::exception& e)
{
std::cerr << "*** ERROR:\n";
std::cerr << e.what();
std::cerr << std::endl;
return exitError;
}
return exitOk;
}
///////////////////////////////////////////////////////////////////////////////
MultiByteToWideChar
的CodePage
參數是錯誤的。 Utf-8與ASCII不同。 您應該使用CP_ACP
,它告訴當前系統代碼頁(與ASCII不同 - 請參閱Unicode,UTF,ASCII,ANSI格式差異 )
大小為零的可能性最大,因為您的測試字符串不是有效的Utf-8字符串。
對於幾乎所有Win32函數,您可以在函數無法獲取詳細的錯誤代碼后調用GetLastError(),因此調用它也會為您提供更多詳細信息。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.