【发布时间】:2014-03-21 05:11:29
【问题描述】:
我正在尝试用 Java 解码包含 % 个编码字符的 URL
我尝试使用 java.net.URI 类来完成这项工作,但它并不总是正常工作。
String test = "https://fr.wikipedia.org/wiki/Fondation_Alliance_fran%C3%A7aise";
URI uri = new URI(test);
System.out.println(uri.getPath());
对于测试字符串“https://fr.wikipedia.org/wiki/Fondation_Alliance_fran%C3%A7aise”,结果是正确的“/wiki/Fondation_Alliance_française”(%C3%A7 正确替换为ç)。
但对于其他一些测试字符串,例如“http://sv.wikipedia.org/wiki/Anv%E4ndare:Lsjbot/Statistik#Drosophilidae”,它给出的结果不正确“/wiki/Anv�ndare:Lsjbot/Statistik”(%E4 被替换为 � 而不是 ä)。
我用 getRawPath() 和 URLDecoder 类做了一些测试。
System.out.println(URLDecoder.decode(uri.getRawPath(), "UTF8"));
System.out.println(URLDecoder.decode(uri.getRawPath(), "ISO-8859-1"));
System.out.println(URLDecoder.decode(uri.getRawPath(), "WINDOWS-1252"));
根据测试字符串,我得到不同编码的正确结果:
- 对于 %C3%A7,使用“UTF-8”编码得到正确结果,使用“ISO-8859-1”或“WINDOWS-1252”编码得到错误结果
- 对于 %E4,情况正好相反。
对于这两个测试 URL,如果我将它们放在 Chrome 地址栏中,我会得到正确的页面。
如何在所有情况下正确解码 URL? 感谢您的帮助
==== 回答====
感谢下面 McDowell 回答中的建议,它现在似乎有效。这是我现在拥有的代码:
private static void appendBytes(ByteArrayOutputStream buf, String data) throws UnsupportedEncodingException {
byte[] b = data.getBytes("UTF8");
buf.write(b, 0, b.length);
}
private static byte[] parseEncodedString(String segment) throws UnsupportedEncodingException {
ByteArrayOutputStream buf = new ByteArrayOutputStream(segment.length());
int last = 0;
int index = 0;
while (index < segment.length()) {
if (segment.charAt(index) == '%') {
appendBytes(buf, segment.substring(last, index));
if ((index < segment.length() + 2) &&
("ABCDEFabcdef0123456789".indexOf(segment.charAt(index + 1)) >= 0) &&
("ABCDEFabcdef0123456789".indexOf(segment.charAt(index + 2)) >= 0)) {
buf.write((byte) Integer.parseInt(segment.substring(index + 1, index + 3), 16));
index += 3;
} else if ((index < segment.length() + 1) &&
(segment.charAt(index + 1) == '%')) {
buf.write((byte) '%');
index += 2;
} else {
buf.write((byte) '%');
index++;
}
last = index;
} else {
index++;
}
}
appendBytes(buf, segment.substring(last));
return buf.toByteArray();
}
private static String parseEncodedString(String segment, Charset... encodings) {
if ((segment == null) || (segment.indexOf('%') < 0)) {
return segment;
}
try {
byte[] data = parseEncodedString(segment);
for (Charset encoding : encodings) {
try {
if (encoding != null) {
return encoding.newDecoder().
onMalformedInput(CodingErrorAction.REPORT).
decode(ByteBuffer.wrap(data)).toString();
}
} catch (CharacterCodingException e) {
// Incorrect encoding, try next one
}
}
} catch (UnsupportedEncodingException e) {
// Nothing to do
}
return segment;
}
【问题讨论】:
-
注意 URLDecoder 不适合解码 URI 路径;它适用于大多数情况,但不是全部。
-
我知道,我只是尝试使用它,因为 URI 类在所有情况下都没有给我正确的答案,并在这个问题中提供更多信息。
标签: java encoding url-encoding