簡體   English   中英

從ASCII轉換為Unicode字符代碼(FreeType2)

[英]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;
}

///////////////////////////////////////////////////////////////////////////////

MultiByteToWideCharCodePage參數是錯誤的。 Utf-8與ASCII不同。 您應該使用CP_ACP ,它告訴當前系統代碼頁(與ASCII不同 - 請參閱Unicode,UTF,ASCII,ANSI格式差異

大小為零的可能性最大,因為您的測試字符串不是有效的Utf-8字符串。

對於幾乎所有Win32函數,您可以在函數無法獲取詳細的錯誤代碼后調用GetLastError(),因此調用它也會為您提供更多詳細信息。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM