我正在尝试在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。 我做错了什么?
答案 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);