【发布时间】:2023-03-11 11:30:02
【问题描述】:
问题:有时我们会收到(对我们而言)编码无效的链接/短语。
下面的示例和我的第一个解决方案
说明: 我必须在应用程序的一部分中修复无效的编码字符串。有时它是一个单词或短语,但有时也是一个 url。当它是一个 URL 时,我只想更改错误编码的字符。如果我使用 ISO 解码并编码为 UTF-8,则特殊的 url 字符也会被编码(/ : ? = &)。我编写了一个解决方案,该解决方案适用于我的案例,但是您将在下面看到的那些哈希对我来说很难闻。
您是否遇到过类似的问题,或者您知道允许解码除某些字符之外的短语的库吗?像这样的:
decode(String value, char[] ignored)
我也想过将 URL 分解成碎片并仅修复路径和查询,但解析它们等会更加混乱。
TLDR:解码 ISO-8858-1 编码的 URL 并将其编码为 UTF-8。不要触摸 URL 特定字符 (/ ? = : &)
输入/输出示例:
// wrong input
"http://some.url/xxx/a/%e4t%fcr%E4/b/%e4t%fcr%E4"
"t%E9l%E9phone"
// good output
"http://some.url/xxx/a/%C3%A4t%C3%BCr%C3%A4/b/%C3%A4t%C3%BCr%C3%A4"
"t%C3%A9l%C3%A9phone"
// very wrong output
"http%3A%2F%2Fsome.url%2Fxxx%2Fa%2F%C3%A4t%C3%BCr%C3%A4%2Fb%2F%C3%A4t%C3%BCr%C3%A4"
我的第一个解决方案:
class EncodingFixer {
private static final String SLASH_HASH = UUID.randomUUID().toString();
private static final String QUESTION_HASH = UUID.randomUUID().toString();
private static final String EQUALS_HASH = UUID.randomUUID().toString();
private static final String AND_HASH = UUID.randomUUID().toString();
private static final String COLON_HASH = UUID.randomUUID().toString();
EncodingFixer() {
}
String fix(String value) {
if (isBlank(value)) {
return value;
}
return tryFix(value);
}
private String tryFix(String str) {
try {
String replaced = replaceWithHashes(str);
String fixed = java.net.URLEncoder.encode(java.net.URLDecoder.decode(replaced, ISO_8859_1), UTF_8);
return replaceBack(fixed);
} catch (Exception e) {
return str;
}
}
private String replaceWithHashes(String str) {
return str
.replaceAll("/", SLASH_HASH)
.replaceAll("\\?", QUESTION_HASH)
.replaceAll("=", EQUALS_HASH)
.replaceAll("&", AND_HASH)
.replaceAll(":", COLON_HASH);
}
private String replaceBack(String fixed) {
return fixed
.replaceAll(SLASH_HASH, "/")
.replaceAll(QUESTION_HASH, "?")
.replaceAll(EQUALS_HASH, "=")
.replaceAll(AND_HASH, "&")
.replaceAll(COLON_HASH, ":");
}
}
或者应该更像:???
检查输入是否为 URL
创建网址
获取路径
按/分割
- 修复每个部分
- 放回原处
- 查询相同,但稍微复杂一点
??
我也考虑过它,但它似乎比上面的那些 replaceAlls 更混乱:/
【问题讨论】:
-
对 URL 编码最大的误解是它是用来对 URL 进行编码的。它不是。它用于对 URL 的查询参数和路径元素进行编码。我强烈建议您将 URL 拆分为基本 URL、附加路径元素和查询参数并分别处理。
-
一个好的经验法则是:任何时候你手动编写某种形式的“编码修复”,你可能做错了什么。
-
很抱歉可能有点迂腐,但您的意思是 ISO-8859-1(请参阅 en.wikipedia.org/wiki/ISO/IEC_8859-1)而不是 ISO-8858-1(iso.org/standard/75885.html),它看起来像是一个特定的 ISO 标准实验室测试的类型(即与字符集无关)?我曾多次遇到定义 8858 的网站,每次都似乎是一个错字。
标签: java encoding utf-8 iso-8859-1