UrlUnescape()和unicode字符

时间:2013-06-13 05:53:07

标签: windows winapi url unicode

我正在尝试在C ++上编写程序,该程序将解码包含一些URL编码的unicode字符的URL编码字符串。

#include <windows.h>
#include <string>
#include <shlwapi.h>
#pragma comment(lib, "Shlwapi.lib")

int _tmain(int argc, _TCHAR* argv[])
{
    std::wstring test = L"bla+%D0%B1%D0%BB%D0%BE%D1%84+%E6%97%A5%E6%9C%AC%E8%AA%9E";
    PWSTR urlencodedStr = const_cast<WCHAR*>(test.c_str());
    WCHAR decodedStr[1025];
    DWORD size = 1024;
    HRESULT hres = UrlUnescape(urlencodedStr, decodedStr, &size, NULL);

    if (hres == S_OK)
        MessageBox(NULL, decodedStr, L"decoded string", MB_OK);

    return 0;
}

我希望在 encodedStr 中获得L“blaблоф日本语”。但我得到L“bla +блоє+æ-¥æœ¬ªªž“而不是。 我在构建中使用unicode charset。 我做错了什么?

2 个答案:

答案 0 :(得分:2)

UrlUnescape默认情况下使用默认(ANSI)代码页将URL解码的%xx字节转换为字符。这几乎不是你想要的。

从Windows 8开始,您可以传递UNESCAPE_AS_UTF8标志以使其运行。如果您不能依赖Win8,则必须使用/编写不受此问题影响的其他URL解码库调用。

还存在+的问题:在普通URL编码中(例如用于路径部分),这意味着加号,但是在form-url-encoding中(例如在查询参数),这就是你在这里看到的,它意味着一个空间。一个好的URL解码器可以让你选择说出你的意思; UrlUnescape没有。另一种方法是在URL解码之前用输入空间手动替换+;这是一个特例,没有其他角色同样受到影响。

答案 1 :(得分:1)

确定。所以我编写了自己的函数来解码带有unicode字符的URL编码字符串。这是:

#include <windows.h>
#include <string>
#include <shlwapi.h>
#include <sstream>
#include <iostream>
#include <wininet.h> // For INTERNET_MAX_URL_LENGTH

#pragma comment(lib, "Shlwapi.lib")

bool IsHexChar(const WCHAR _char)
{
    return ((_char == L'A') || 
            (_char == L'B') ||
            (_char == L'C') ||
            (_char == L'D') ||
            (_char == L'E') ||
            (_char == L'F') || 
            iswalnum(_char));
}

std::wstring UrlDecode(const std::wstring& _encodedStr)
{
    std::string charStr;

    for (size_t i = 0; i < _encodedStr.length(); ++i)
    {
        if ((_encodedStr[i] == L'%') && (IsHexChar(_encodedStr[i+1])) && (IsHexChar(_encodedStr[i+2])))
        {
            std::wstring hexCodeStr = L"0x";
            hexCodeStr += _encodedStr[i+1];
            hexCodeStr += _encodedStr[i+2];

            unsigned int hexCharCode;   
            std::wstringstream ss;
            ss << std::hex << hexCodeStr;
            ss >> hexCharCode;

            charStr += static_cast<char>(hexCharCode);

            i += 2;
        }
        else if (_encodedStr[i] == L'+')
            charStr += L' ';
        else
            charStr += _encodedStr[i];
    }

    WCHAR decodedStr[INTERNET_MAX_URL_LENGTH];
    MultiByteToWideChar(CP_UTF8, 0, charStr.c_str(), -1, decodedStr, sizeof(decodedStr));

    return decodedStr;
}

像这样使用:

std::wstring encodedStr = L"bla+%D0%B1%D0%BB%D0%BE%D1%84+%E6%97%A5%E6%9C%AC%E8%AA%9E";
std::wstring decodedStr = UrlDecode(encodedStr);