开发者工具 · URL 编码器和解码器
百分比编码的工作原理:从字符到 UTF-8 字节到 %XX 序列
· 工作原理
url 编码 utf-8 百分比编码 开发人员
百分比编码不编码字符;它对字节进行编码。这篇文章展示了一个字符如何变成 UTF-8 字节,然后变成十六进制对,以及为什么重音字母需要两个 %XX 组,而表情符号需要四个。
为什么 'é' 变成 %C3%A9 而不是 %E9 — 揭示底层字节层的观察结果
当初级开发人员在 URL 中看到 %C3%A9 时,百分比编码对字节而不是字符进行操作。字符 é 不是一个字节; UTF-8 将其编码为两个:C3 A9。 RFC 3986 中的百分比编码规则很简单:将每个字节编码为百分号后跟两个十六进制数字。这种区别将解释从神秘转变为合乎逻辑。
了解百分比编码需要了解 UTF-8。文本必须使用字符编码转换为字节。 UTF-8 是 URL 和 Web 的标准。它将字符表示为可变长度字节序列:ASCII 使用一个字节,重音字母使用两个字节,表情符号使用四个字节。每个阶段都是不同的:字符、Unicode 代码点、UTF-8 字节,然后是 %XX 对。在不理解字节的情况下跳到十六进制就没有抓住重点。
RFC 3986 的百分比编码规则 — 每个字节一个 % 后跟两个十六进制数字,首选大写
RFC 3986 定义了一个规则:将每个字节编码为百分比后跟两个大写十六进制数字。不需要编码的非保留字符是字母、数字、连字符、下划线、句点和波形符。其他一切都必须编码。空格变为 %20,斜线变为 %2F,百分号变为 %25。这可以防止查询值中的特殊字符破坏 URL 结构。
空格编码为字节 0x20,成为 %20。正斜杠是 0x2F,变成 %2F。这些是需要一个字节的 ASCII 字符。重音字母和表情符号不同。百分号变为 %25。保留的分隔符(如冒号)被编码以保留结构。这可以防止查询参数中嵌入的“&”或“等于”破坏解析。每个字节变成%HH。
UTF-8 作为假定的字符集 — 为什么现代 URL 是 UTF-8 以及遗留异常在哪里
UTF-8 使用可变长度编码。从代码点 0 到 127 的 ASCII 是一个字节。从 128 到 2047 的字符(包括带重音的拉丁字母)是两个字节。东亚文字中常见的从 2048 到 65535 的字符为三个字节。 65535 以上的字符(包括大多数表情符号)为四个字节。每个字节都以表示后面有多少字节的位作为前缀。
带重音的字母 é 是 Unicode 代码点 U+00E9。 UTF-8 将其编码为两个字节:0xC3 和 0xA9。百分比编码产生%C3%A9。德语 ü (U+00FC) 编码为 0xC3 0xBC,变成 %C3%BC。西班牙语 ñ (U+00F1) 编码为 0xC3 0xB1,变成 %C3%B1。该模式是一致的:第一个字节表示一个两字节序列。在编码中,一个带重音的字母会扩展六个字符。
工作示例:逐字节编码“café 😀” — 代码点、UTF-8 字节和结果字符串
Emoji 使字节层变得明显。竖起大拇指的表情符号👍是代码点U+1F44D。 UTF-8 将其编码为四个字节:F0 9F 91 8D。百分比编码生成 %F0%9F%918D:1 个符号对应 12 个字符。笑脸 😀 (U+1F600) 编码为 F0 9F 98 80,变成 %F0%9F%9880。四字节序列变成百分之十二编码的字符。
混合文本说明了为什么理解字节很重要。短语“café 😀”包含纯 ASCII、重音符号和表情符号。字母 c、a、f 编码为 63、61、66。 é 编码为 C3 A9。空格编码为 20。表情符号编码为 F0 9F 98 80。结果是“caf%C3%A9%20%F0%9F%9880”。了解哪些字节需要编码可以使输出变得可预测。
反向解码 — 将 %XX 组收集到字节中,然后将它们解释为 UTF-8
解码则反转该过程。解码器扫描 %XX 对并将它们收集为字节值。看到%C3%A9,它提取字节C3和A9。 UTF-8 解码将它们解释为字符 é。如果序列不完整,例如单独的 %C3,则结果是错误。解码器从 UTF-8 前缀位得知 C3 需要第二个字节。
十六进制数字中大小写无关紧要; %C3%A9 和 %c3%a9 解码相同。 RFC 允许使用大写或小写,但首选大写。但字符的大小写很重要:é(如 %C3%A9)与 É(如 %C3%89)不同。 URL 比较必须标准化百分比编码,否则可能会将相同的资源视为不同的资源。框架在缓存之前进行标准化。
为什么大小写在十六进制数字中并不重要,但在其他地方却很重要 - 规范化规则和 URL 比较
RFC 3986 提到域名的 punycode 和提交的表单编码作为单独的规则。 Punycode 对不带百分号的非 ASCII 域名进行编码,以实现 DNS 兼容性。域名 😀.example 变为“xn--js8h.example”。表单编码修改百分比编码,但有一个例外:空格变成加号而不是 %20。作为 application/x-www-form-urlencoded 提交的表格使用加号作为空格。
URL 编码器工具显示所有三种模式:组件编码、整体 URL 编码和表单编码。使用encodeURIComponent进行组件编码对每个特殊字符(包括分隔符)进行编码,适合查询值。使用encodeURI 进行整个URL 编码可保留完整URL 的结构字符。表单编码适用于 POST 正文。每个都使用 UTF-8;它们的区别仅在于哪些字节未编码。
Punycode 和表单编码:同级标准,而不是百分比编码扩展
字节视角解决了 URL 之谜。为什么一个表情符号需要十二个字符?因为 UTF-8 使用四个字节,每个字节变成 %HH。为什么有些 URL 带有 %2F 斜杠,而其他 URL 则带有普通斜杠?因为编码模式决定:路径段中的斜杠保持未编码,但在查询值内它必须是 %2F 以避免误读。
以字节为单位考虑可预测的百分比编码。字符是一个 Unicode 代码点。 UTF-8 是其字节表示形式。百分比编码是传输格式。字符扩展发生在 UTF-8 层。十六进制大小写不影响解码,但字符大小写会影响。由于严格的前缀规则,无效字节序列在 UTF-8 处失败。 URL 编码器工具显示了这一进展。
要点:以字节为单位思考 — URL 编码器和解码器如何在浏览器中为您粘贴的任何文本显示准确的 %XX 输出
工作示例:编码“café 😀”。单词咖啡馆包含字母 c、a、f 作为 ASCII 单字节:63、61、66。 é 是 UTF-8 两个字节:C3 A9。空间为 20。表情符号😀有四个字节:F0 9F 98 80。未保留的 ASCII 字母保持可见。结果:“caf%C3%A9%20%F0%9F%9880”。这说明了为什么一个表情符号扩展到十二个字符。
要点:以字节为单位思考,而不是字符。百分比编码在 UTF-8 编码之后应用。每个字节变成%HH。可变长度 UTF-8 意味着字符扩展不同:ASCII 变为 %XX(两个字符),两字节重音变为 %XX%XX(六个字符),四字节表情符号变为 %XX%XX%XX%XX(十二个字符)。将文本粘贴到 URL 编码器工具中并观察进度。