我有几次这个例外,并且不明白它是如何错误的下划线。我一直在堆栈溢出和互联网上搜索一堆,但我还没有看到任何可以解释为什么我在域中收到关于下划线的错误的原因。
注意:我不能故意复制它;我已经尝试将字符串"https://11.111.1.111:1111/publicapi/v1/aaaaa/AAAAAa1aAAA1a11aaAaAA1aaa11AAAaaA1AAaAAA1aaA11A_aaaAaAaA1aaAaaaaaAAaa1Aa-Aa1AAAAAAA1Aa"
传递给new java.net.URI(...)
,但它并没有错误。
注意:我用' A'替换了敏感的大写字母字符。使用' a'和小写字母字符,其他网址与错误的网址相同。
Android: 4.4.4
Manufacturer: LGE
Model: Nexus 5
Date: Wed Nov 26 16:26:10 MST 2014
java.net.URISyntaxException: Illegal character in path at index 94: https://11.111.1.111:1111/publicapi/v1/aaaaa/AAAAAa1aAAA1a11aaAaAA1aaa11AAAaaA1AAaAAA1aaA11A_aaaAaAaA1aaAaaaaaAAaa1Aa-Aa1AAAAAAA1Aa
at libcore.net.UriCodec.validate(UriCodec.java:63)
at java.net.URI.parseURI(URI.java:402)
at java.net.URI.<init>(URI.java:204)
at [redacted]._doRequestCore([redacted].java:205)
... [redacted] ...
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:841)
[编辑] ._ doRequestCore第205行:
request.setURI(new java.net.URI(baseurl + relurl));
变量的类型有:
String baseurl
String relurl
org.apache.http.client.methods.HttpRequestBase request
baseurl是"https://11.111.1.111:1111/publicapi"
,我只能假设relurl一定是:
"/v1/aaaaa/AAAAAa1aAAA1a11aaAaAA1aaa11AAAaaA1AAaAAA1aaA11A_aaaAaAaA1aaAaaaaaAAaa1Aa-Aa1AAAAAAA1Aa"
网址肯定已经编码,通过以下方式编码:
String relurl = android.net.Uri.parse("/v1/aaaaa/")
.buildUpon()
.appendPath("AAAAAa1aAAA1a11aaAaAA1aaa11AAAaaA1AAaAAA1aaA11A_aaaAaAaA1aaAaaaaaAAaa1Aa-Aa1AAAAAAA1Aa")
.build().toString();
但是,编码似乎并没有将下划线编码为转义的八位字节,就像我不希望的那样。我查看了相应版本的UriCodec.java validate():63 - 它调用了抽象的isRetained():
// https://android.googlesource.com/platform/libcore/+/15a93894f19b27f3d85b8e3c3de8cff8a33964d3/luni/src/main/java/libcore/net/UriCodec.java
public abstract class UriCodec {
/**
* Returns true if {@code c} does not need to be escaped.
*/
protected abstract boolean isRetained(char c);
/**
* Throws if {@code s} is invalid according to this encoder.
*/
public final String validate(String uri, int start, int end, String name)
throws URISyntaxException {
for (int i = start; i < end; ) {
char ch = uri.charAt(i);
if ((ch >= 'a' && ch <= 'z')
|| (ch >= 'A' && ch <= 'Z')
|| (ch >= '0' && ch <= '9')
-> || isRetained(ch)) {
i++;
} else if (ch == '%') {
if (i + 2 >= end) {
throw new URISyntaxException(uri, "Incomplete % sequence in " + name, i);
}
int d1 = hexToInt(uri.charAt(i + 1));
int d2 = hexToInt(uri.charAt(i + 2));
if (d1 == -1 || d2 == -1) {
throw new URISyntaxException(uri, "Invalid % sequence: "
+ uri.substring(i, i + 3) + " in " + name, i);
}
i += 3;
} else {
63: throw new URISyntaxException(uri, "Illegal character in " + name, i);
}
}
return uri.substring(start, end);
}
...
但是被URI.java的PartEncoder成员类覆盖了以检查UNRESERVED,它肯定有下划线:
// https://android.googlesource.com/platform/libcore/+/android-4.4.4_r2/luni/src/main/java/java/net/URI.java
static final String UNRESERVED = "_-!.~\'()*";
...
static final UriCodec PATH_ENCODER = new PartEncoder("/@");
...
private static class PartEncoder extends UriCodec {
private final String extraLegalCharacters;
PartEncoder(String extraLegalCharacters) {
this.extraLegalCharacters = extraLegalCharacters;
}
@Override protected boolean isRetained(char c) {
-> return UNRESERVED.indexOf(c) != -1
|| PUNCTUATION.indexOf(c) != -1
|| extraLegalCharacters.indexOf(c) != -1
|| (c > 127 && !Character.isSpaceChar(c) && !Character.isISOControl(c));
}
}
第402行的parseURI是:
path = PATH_ENCODER.validate(uri, fileStart, queryStart, "path");
自从android 4.4.4以来,我确实看到this commit has been made到该文件,但这看起来只会影响域,而不是路径段。
我只是不知道这最终会如何产生该异常,该url对我来说看起来非常有效,并且正在进行进一步的测试。任何人都能看到我失踪的东西?我真的不喜欢因为不理解而让例外情况发生。我唯一的假设是,网址中有一个unicode字符,在报告异常时会以某种方式被剥夺 - 似乎不太可能。