2

我正在尝试在 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;
}

我期待在 decodedStr 中获得 L"bla блоф 日本语"。但我得到的是 L"bla+блоф+日本語"。我在构建中使用 unicode 字符集。我究竟做错了什么?

4

2 回答 2

2

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

从 Windows 8 开始,您可以传递UNESCAPE_AS_UTF8标志以使其正常运行。如果你不能依赖 Win8,你将不得不使用/编写一个不同的 URL 解码库调用,它不会受到这个问题的影响。

还有一个问题+: 在纯 URL 编码中(例如用于路径部分),这意味着一个加号,但在 form-url-encoding 中(例如在查询参数中),这就是你好像有这里,就意味着一个空间。一个好的 URL 解码器可以让您选择说出您的意思;UrlUnescape才不是。另一种方法是在 URL 解码之前手动替换+输入的空格;这是一种特殊情况,没有其他字符受到类似影响。

于 2013-06-13T09:48:09.630 回答
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);
于 2013-06-13T13:53:22.033 回答