2013-06-13 57 views
2

我想在C++上編寫程序,該程序將解碼包含一些URL編碼的Unicode字符的URL編碼的字符串。UrlUnescape()和Unicode字符

#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 「喇嘛блоф日本語」。但是我得到了L「bla +блоÑ」+æ-¥æœèèžž「。 我在我的版本中使用unicode字符集。 我在做什麼錯?

回答

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); 
2

UrlUnescape默認情況下,使用默認(ANSI)代碼頁將URL解碼的%xx字節轉換爲字符。這幾乎從來都不是你想要的。

從Windows 8開始,您可以通過UNESCAPE_AS_UTF8標誌使其行爲。如果你不能依賴於Win8,你將不得不使用/編寫一個不受此問題影響的不同的URL解碼庫調用。

另外還有+的問題:在plain-URL-encoding(例如用於路徑部分)中,這意味着加號,但是在form-url-encoding(例如在查詢參數中) ,這就是你在這裏所看到的,它意味着一個空間。一個好的URL解碼器會給你選擇你說的是哪一個; UrlUnescape沒有。另一種方法是在URL解碼之前用輸入空間手動替換+;這是一種特殊情況,其他字符也不會受到類似的影響。