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
),我也试过用AnsiString
和char 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%可靠的。
这就像一个魅力,非常感谢! –
我使用的是UrlCanonicalize(),但InternetCanonicalizeUrl不知道关于utf-8/unicode-16的解释帮助我以同样的方式解决了这个问题@remy上面显示 - 谢谢! – estoy