用Java解析URL会给我URL中错误的编码字符
当我执行以下操作时:用Java解析URL会给我URL中错误的编码字符,java,character-encoding,url-encoding,Java,Character Encoding,Url Encoding,当我执行以下操作时: try { URL url = new URL(urlAsString); //using proxy may increase latency HttpURLConnection hConn = (HttpURLConnection) url.openConnection(Proxy.NO_PROXY); // force no follow hConn.setInstanceFollowRedirects(false);
try {
URL url = new URL(urlAsString);
//using proxy may increase latency
HttpURLConnection hConn = (HttpURLConnection) url.openConnection(Proxy.NO_PROXY);
// force no follow
hConn.setInstanceFollowRedirects(false);
// the program doesn't care what the content actually is
hConn.setRequestMethod("HEAD");
// default is 0 => infinity waiting
hConn.setConnectTimeout(timeout);
hConn.setReadTimeout(timeout);
hConn.connect();
int responseCode = hConn.getResponseCode();
hConn.getInputStream().close();
if (responseCode == HttpURLConnection.HTTP_OK)
return urlAsString;
String loc = hConn.getHeaderField("Location");
if (responseCode == HttpURLConnection.HTTP_MOVED_PERM && loc != null)
return loc.replaceAll(" ", "+");
} catch (Exception ex) {
}
return "";
对于该url:我得到
-重新设计——然后一切都会破裂/
这是错误的。Firefox决心
代码中有什么错误?没有错误。不同之处在于,m-破折号在不同的编码中表示不同。因此,如果Firefox使用的编码与您的程序不同,您将看到不同的字符 在你的情况下,两者都是正确的。这只是编码的问题。在Java中,您使用UTF-8,即:;而您在FF中看到的似乎是ISO-8859 如果要在Java中生成与Firefox相同的结果,请尝试以下操作:
System.out.print(URLEncoder.encode(loc.replace(" ", "+"), "ISO-8859-1"));
它将打印您在Firefox中看到的内容。(显然,它也会对
/
和:
进行编码。但只是为了演示一下)没有什么错。不同之处在于,m-破折号在不同的编码中表示不同。因此,如果Firefox使用的编码与您的程序不同,您将看到不同的字符
在你的情况下,两者都是正确的。这只是编码的问题。在Java中,您使用UTF-8,即:;而您在FF中看到的似乎是ISO-8859
如果要在Java中生成与Firefox相同的结果,请尝试以下操作:
System.out.print(URLEncoder.encode(loc.replace(" ", "+"), "ISO-8859-1"));
它将打印您在Firefox中看到的内容。(显然,它也将编码/
和:
。但仅用于演示)根据,HTTP头值通常应使用ISO-8859-1进行编码
在这里,bit.ly发送了一个错误的响应-Location:header使用UTF-8编码,因此em破折号字符由三个单独的字节(0xe2、0x80、0x94)表示
HttpURLConnection
使用ISO-8859-1对字节进行解码,使它们变成三个字符(和两个未定义的字符),但看起来好像在应用URL编码之前使用UTF-8对它们进行了重新编码(每个字符产生两个字节,因为这三个字符的值均大于等于0x80)
Firefox很可能将数据视为ISO-8859-1;然后,当稍后应用URL编码时,问题将自行消除
您也可以通过URL编码getHeaderField()
返回的值来实现这一点;由于Unicode范围U+0080到U+00FF与ISO-8859-1字节范围0x80-0xFF相同,因此可以通过将非ASCII字符强制转换为int
值对其进行编码:
/**
* Takes a URI that was decoded as ISO-8859-1 and applies percent-encoding
* to non-ASCII characters. Workaround for broken origin servers that send
* UTF-8 in the Location: header.
*/
static String encodeUriFromHeader(String uri) {
StringBuilder sb = new StringBuilder();
for(char ch : badLocation.toCharArray()) {
if(ch < (char)128) {
sb.append(ch);
} else {
// this is ONLY valid if the uri was decoded using ISO-8859-1
sb.append(String.format("%%%02X", (int)ch));
}
}
return sb.toString();
}
/**
*获取已解码为ISO-8859-1的URI并应用百分比编码
*转换为非ASCII字符。发送数据的损坏源服务器的解决方法
*UTF-8位于位置:标头。
*/
静态字符串encodeUriFromHeader(字符串uri){
StringBuilder sb=新的StringBuilder();
for(char ch:badLocation.toCharArray()){
if(ch<(char)128){
某人附加(ch);
}否则{
//这仅在使用ISO-8859-1解码uri时有效
sb.append(String.format(“%%%02X”,(int)ch));
}
}
使某人返回字符串();
}
根据,HTTP头值通常应使用ISO-8859-1编码
在这里,bit.ly发送了一个错误的响应-Location:header使用UTF-8编码,因此em破折号字符由三个单独的字节(0xe2、0x80、0x94)表示
HttpURLConnection
使用ISO-8859-1对字节进行解码,使它们变成三个字符(和两个未定义的字符),但看起来好像在应用URL编码之前使用UTF-8对它们进行了重新编码(每个字符产生两个字节,因为这三个字符的值均大于等于0x80)
Firefox很可能将数据视为ISO-8859-1;然后,当稍后应用URL编码时,问题将自行消除
您也可以通过URL编码getHeaderField()
返回的值来实现这一点;由于Unicode范围U+0080到U+00FF与ISO-8859-1字节范围0x80-0xFF相同,因此可以通过将非ASCII字符强制转换为int
值对其进行编码:
/**
* Takes a URI that was decoded as ISO-8859-1 and applies percent-encoding
* to non-ASCII characters. Workaround for broken origin servers that send
* UTF-8 in the Location: header.
*/
static String encodeUriFromHeader(String uri) {
StringBuilder sb = new StringBuilder();
for(char ch : badLocation.toCharArray()) {
if(ch < (char)128) {
sb.append(ch);
} else {
// this is ONLY valid if the uri was decoded using ISO-8859-1
sb.append(String.format("%%%02X", (int)ch));
}
}
return sb.toString();
}
/**
*获取已解码为ISO-8859-1的URI并应用百分比编码
*转换为非ASCII字符。发送数据的损坏源服务器的解决方法
*UTF-8位于位置:标头。
*/
静态字符串encodeUriFromHeader(字符串uri){
StringBuilder sb=新的StringBuilder();
for(char ch:badLocation.toCharArray()){
if(ch<(char)128){
某人附加(ch);
}否则{
//这仅在使用ISO-8859-1解码uri时有效
sb.append(String.format(“%%%02X”,(int)ch));
}
}
使某人返回字符串();
}
事实上,情况正好相反。不正确的一个用ISO8859-1(或CP1252)编码,正确的一个用UTF-8编码。@BalusC-hmm。。。我没听懂你的意思。我说的是UTF-8是推荐的——这是正确的。FF可能使用依赖于平台的编码.Hmmh,但是为什么我需要对url位置进行编码呢?它不是已经编码了吗?是的,这个额外的编码不起作用。但我想我应该把标题读成ISO-8859-1,以获得正确的位置。hmmh,hConn.getContentType()是text/html;charset=utf-8实际上是相反的。不正确的一个用ISO8859-1(或CP1252)编码,正确的一个用UTF-8编码。@BalusC-hmm。。。我没听懂你的意思。我说的是UTF-8是推荐的——这是正确的。FF可能使用依赖于平台的编码.Hmmh,但是为什么我需要对url位置进行编码呢?它不是已经编码了吗?是的,这个额外的编码不起作用。但我想我应该把标题读成ISO-8859-1,以获得正确的位置。hmmh,hConn.getContentType()是text/html;charset=utf-8我是否需要为该位置应用url编码?顺便说一句:我应用编码是偶然的。我将url复制到firefox的url栏中,然后从那里粘贴到这个问题中。Firefox应用了编码。。。我把它修好了post@SimonJ所以我应该向bit.ly或c提交一份bug报告