InternetCanonicalizeUrl失败,我有很多在处理某些字符转换成一个URL的烦恼解码音调符号字母

问题描述:

,让我们假设我有以下网址:InternetCanonicalizeUrl失败,我有很多在处理某些字符转换成一个URL的烦恼解码音调符号字母

的http://本地主机/ somewere /在MyLibrary。 ?DLL/REST /什么参数=一%C3%A1lisis

必须转换为:

HTTP://localhost/somewere/myLibrary.dll/rest/something?parameter=Análisis

为了解决变音符号的解码问题,我决定使用InternetCanonicalizeUrl函数,因为我正在使用的应用程序只能在Windows中工作,而且我不想安装额外的库,我使用的辅助函数如下:

String DecodeURL(const String &a_URL) 
{ 
    String result; 
    unsigned long size = a_reportType.Length() * 2; 
    wchar_t *buffer = new wchar_t[size]; 

    if (InternetCanonicalizeUrlW(a_URL.c_str(), buffer, &size, ICU_DECODE | ICU_NO_ENCODE)) 
    { 
     result = buffer; 
    } 

    delete [] buffer; 
    return result; 
} 

这一工程样的好,几乎穿过它,除了音调符号的字母URL中的任何,如下我的例子URL进行解码:

http:// localh OST/somewere/myLibrary.dll/REST /什么?参数=Análisis

我正在使用的IDE是CodeGear的™C++Builder®2009年(这就是为什么我*使用String而不是std::string),我也试过用AnsiStringchar buffer版本,结果相同。

有关如何处理此错误的任何提示/备选方法?

在此先感谢。

InternetCanonicalizeUrl()正在做正确的事情,你只需要考虑到它实际上在做什么。

URL不支持Unicode(IRI),所以Unicode数据必须字符集编码为字节八位字节,然后根据需要使用%HH序列对这些八位字节进行url编码。在这种情况下,数据被编码为UTF-8(在当今很多URL中并不少见,但也不能保证),但InternetCanonicalizeUrl()无法知道,因为URL没有描述正在使用哪个charset的语法。它所能做的只是将%HH序列解码为相关的字节八位位组值,它不能对您的八位字节进行字符集解码。在Unicode版本的情况下,InternetCanonicalizeUrlW()按原样返回那些字节值,作为wchar_t元素。但无论哪种方式,您都必须自己对八位字节进行字符解码以恢复原始的Unicode数据。

因此,在这种情况下你可以做的是将解码后的数据复制到UTF8String,然后指定/返回String,以便将其解码为UTF-16。这当然只适用于UTF-8编码的URL。例如:

String DecodeURL(const String &a_URL) 
{ 
    DWORD size = 0; 
    if (!InternetCanonicalizeUrlW(a_URL.c_str(), NULL, &size, ICU_DECODE | ICU_NO_ENCODE)) 
    { 
     if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) 
     { 
      String buffer; 
      buffer.SetLength(size-1); 
      if (InternetCanonicalizeUrlW(a_URL.c_str(), buffer.c_str(), &size, ICU_DECODE | ICU_NO_ENCODE)) 
      { 
       UTF8String utf8; 
       utf8.SetLength(buffer.Length()); 
       for (int i = 1; i <= buffer.Length(); ++i) 
        utf8[i] = (char) buffer[i]; 
       return utf8; 
      } 
     } 
    } 

    return String(); 
} 

或者:

// encoded URLs are always ASCII, so it is safe 
// to pass an encoded URL UnicodeString as an 
// AnsiString... 
String DecodeURL(const AnsiString &a_URL) 
{ 
    DWORD size = 0; 
    if (!InternetCanonicalizeUrlA(a_URL.c_str(), NULL, &size, ICU_DECODE | ICU_NO_ENCODE)) 
    { 
     if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) 
     { 
      UTF8String buffer; 
      buffer.SetLength(size-1); 
      if (InternetCanonicalizeUrlA(a_URL.c_str(), buffer.c_str(), &size, ICU_DECODE | ICU_NO_ENCODE)) 
      { 
       return utf8; 
      } 
     } 
    } 

FYI,C++生成器附带印地预装。印有TIdURI类,它可以解码URL,并采取字符集的考虑,如:

#include <IdGlobal.hpp> 
#include <IdURI.hpp> 

String DecodeURL(const String &a_URL) 
{ 
    return TIdURI::URLDecode(URL, enUTF8); 
} 

在任何情况下,你必须知道用于编码URL数据的字符集。如果你不这样做,你所能做的就是解码原始八位字节,然后使用启发式分析来猜测字符集可能是什么,但是对于非ASCII和非UTF字符集,这不是100%可靠的。

+0

这就像一个魅力,非常感谢! –

+0

我使用的是UrlCanonicalize(),但InternetCanonicalizeUrl不知道关于utf-8/unicode-16的解释帮助我以同样的方式解决了这个问题@remy上面显示 - 谢谢! – estoy